python3-基础8
模块与包
什么是模块
模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
#在python中,模块的使用方式都是一样的,但其实细说的话,模块可以分为四个通用类别:
1 使用python编写的.py文件,是被导入使用的
2 已被编译为共享库或DLL的C或C++扩展
3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包),包就是包含init的文件夹,也是被导入使用的
4 使用C编写并链接到python解释器的内置模块
导入模块干了那些事
1、执行源文件
2、以源文件为基础产生一个全局名称空间,如果调用源空间中的函数,用.就行,作用域关系在调用的时候就已经固定了。
3、再当前位置拿到一个模块名,指向2创建的名称空间
import 使用
别名 用 as
1 import spam as sm
2 print(sm.money)
一行中导入多个模块,用逗号隔开
import os,sys,spam
自定义模块、内置模块、第三方模块、包 等等
from ... inmport ... 用法
from...import * # *代表所有(除了横杆开头的名字,如 _money()),一般不建议用,
#也可以在模块开头增加 __all__=['money','x','y'] 来控制*的识别范围,
#_ 和 __all__ 只是对from...import * 有用
#from sys import * 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置
#大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
#优点:使用源文件内的名字时无需加前缀,使用方便
#缺点:容易与当前文件的名称空间内的名字混淆
#可以起别名
# from spam import money as m
==============
'''
查找模块
模块只有在第一次导入时才会执行,之后的导入都是直接引用内存中已经存在的结果
import sys
print(sys.modules) #一个字典,存放的是已经加载到内存的模块
print(sys.path) #一个列表,存放的是当前执行文件的路径
模块的搜索路径
import sys
先从哪里找?
先从内存里找,然后再去硬盘上找
python文件修改完后一定要重启程序,重新加载一遍才会生效
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
比如找abc\abc.py模块,若内存中和硬盘中都找不到,那就要去sys.path中找,这就需要吧abc.py所在的目录路径添加到sys.path里去
sys.path.append(r'C:\Users\Administrator\PycharmProjects\python\abc') #将目录添加到最后
sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\python\abc') #将目前插到最前面,找到的更快
注意:自定义的模块一定不要与python自带的模块名重名
要明确 执行文件是谁,被导入的文件是谁
'''
'''
两种使用方法:
被当做脚本使用
被当做模块使用
__name__
#文件当做脚本运行时__name__等于__main__
#文件当做模块被加载运行时__name__等于模块名
写模块时添加如下代码(只有被当做脚本使用时,才会执行if里的代码):
if __name__ == '__main__':
#当做脚本使用
func1()
func2()
func3()
#导入模块实际上就是导入文件下的 __init__.py 文件
#开发者通过修改 __init__.py 文件,方便使用者调用函数
#1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
#2、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
#3、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
三步:
1、执行文件
2、产生名称空间
3、调用函数
绝对导入与相对导入
我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以glance作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py
# 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
# 优点: 执行文件与被导入的模块中都可以使用
# 缺点: 所有导入都是以sys.path为起始点,导入麻烦
# 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
# 符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
# 优点: 导入更加简单
# 缺点: 只能在导入包中的模块时才能使用
#注意:
1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
2. attempted relative import beyond top-level package # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包
软件开发规范:
bin 目录下是执行文件
conf 目录下是控制文件
lib 目录下是本程序需要依赖或开发的功能模块文件
log 目录下是日志文件
db 目录下存放数据文件
core 目录下存放核心的逻辑
Readme
示例 :

###############
#===============>star.py
import sys,os
##该文件所在位置:D:\第1层\第2层\第3层\第4层\第5层\test_gfh.py
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 获取当前运行脚本的绝对路径
'''
如果直接在python console 中或者命令行中运行上面代码,则会报如下错误:
NameError: name '__file__' is not defined 原因是:‘__file__'这个参数代表的是python解释器正在执行的脚本文件,如果直接在命令行运行上面两行代码,则python解释器找不到正在执行的脚本文件,即我们将它写在一个脚本文件中,再在解释器中运行这个脚本文件就ok了 '''
sys.path.append(BASE_DIR) #将路径添加到sys.path from core import src if __name__ == '__main__':
src.run()
#===============>settings.py
import os BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DB_PATH=os.path.join(BASE_DIR,'db','db.json')
LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
LOGIN_TIMEOUT=5 """
logging配置
"""
# 定义三种日志输出格式
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' # log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {},
'handlers': {
#打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
#打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': LOG_PATH, # 日志文件
'maxBytes': 1024*1024*5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
#logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
},
},
} #===============>src.py
from conf import settings
from lib import common
import time logger=common.get_logger(__name__) current_user={'user':None,'login_time':None,'timeout':int(settings.LOGIN_TIMEOUT)}
def auth(func):
def wrapper(*args,**kwargs):
if current_user['user']:
interval=time.time()-current_user['login_time']
if interval < current_user['timeout']:
return func(*args,**kwargs)
name = input('name>>: ')
password = input('password>>: ')
db=common.conn_db()
if db.get(name):
if password == db.get(name).get('password'):
logger.info('登录成功')
current_user['user']=name
current_user['login_time']=time.time()
return func(*args,**kwargs)
else:
logger.error('用户名不存在') return wrapper @auth
def buy():
print('buy...') @auth
def run(): print('''
购物
查看余额
转账
''')
while True:
choice = input('>>: ').strip()
if not choice:continue
if choice == '':
buy() #===============>db.json
{"egon": {"password": "", "money": 3000}, "alex": {"password": "alex3714", "money": 30000}, "wsb": {"password": "", "money": 20000}} #===============>common.py
from conf import settings
import logging
import logging.config
import json def get_logger(name):
logging.config.dictConfig(settings.LOGGING_DIC) # 导入上面定义的logging配置
logger = logging.getLogger(name) # 生成一个log实例
return logger def conn_db():
db_path=settings.DB_PATH
dic=json.load(open(db_path,'r',encoding='utf-8'))
return dic #===============>access.log
[2017-10-21 19:08:20,285][MainThread:10900][task_id:core.src][src.py:19][INFO][登录成功]
[2017-10-21 19:08:32,206][MainThread:10900][task_id:core.src][src.py:19][INFO][登录成功]
[2017-10-21 19:08:37,166][MainThread:10900][task_id:core.src][src.py:24][ERROR][用户名不存在]
[2017-10-21 19:08:39,535][MainThread:10900][task_id:core.src][src.py:24][ERROR][用户名不存在]
python3-基础8的更多相关文章
- python3基础视频教程
随着目前Python行业的薪资水平越来越高,很多人想加入该行业拿高薪.有没有想通过视频教程入门的同学们?这份Python教程全集等你来学习啦! python3基础视频教程:http://pan.bai ...
- Python3基础-特别函数(map filter partial reduces sorted)实例学习
1. 装饰器 关于Python装饰器的讲解,网上一搜有很多资料,有些资料讲的很详细.因此,我不再详述,我会给出一些连接,帮助理解. 探究functools模块wraps装饰器的用途 案例1 impor ...
- 2. Python3 基础入门
Python3 基础入门 编码 在python3中,默认情况下以UTF-8编码.所有字符串都是 unicode 字符串,当然也可以指定不同编码.体验过2.x版本的编码问题,才知道什么叫难受. # -* ...
- python002 Python3 基础语法
python002 Python3 基础语法 编码默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 当然你也可以为源码文件指定不同的编码: # -* ...
- Python3基础(十二) 学习总结·附PDF
Python是一门强大的解释型.面向对象的高级程序设计语言,它优雅.简单.可移植.易扩展,可用于桌面应用.系统编程.数据库编程.网络编程.web开发.图像处理.人工智能.数学应用.文本处理等等. 在学 ...
- Python3基础(八) 模块
在程序中定义函数可以实现代码重用.但当你的代码逐渐变得庞大时,你可能想要把它分割成几个文件,以便能够更简单地维护.同时,你希望在一个文件中写的代码能够被其他文件所重用,这时我们应该使用模块(modul ...
- 【python3基础】python3 神坑笔记
目录 os 篇 os.listdir(path) 运算符篇 is vs. == 实例 1:判断两个整数相等 实例 2:argparse 传参 实例 3:np.where 命令行参数篇 Referenc ...
- Python3基础语法和数据类型
Python3基础语法 编码 默认情况下,Python3源文件以UTF-8编码,所有字符串都是unicode字符串.当然你也可以为原码文件制定不同的编码: # -*- coding: 编码 -*- 标 ...
- Python3基础-目录
Python3基础-目录(Tips:长期更新Python3目录) 第一章 初识Python3 1.1 Python3基础-前言 1.2 Python3基础-规范 第二章 Python3内置函数&a ...
- Python3基础1
Python介绍及特点 发展史 Python 2 or 3? 安装Python3 Hello World程序 变量 用户输入 模块初识 .pyc是个什么? 数据类型初识 数据运算 表达式if ...e ...
随机推荐
- npm -g -D -s的区别
npm install module-name 全局安装 npm install module-name -D 即 npm install module-name -save-dev 保存到devD ...
- gulp的使用(一)之gulp的基础了解
Gulp是一个工具.用于项目构建. Gulp简介: 多个开发者共同开发一个项目,每位开发者负责不同的模块,这就会造成一个完整的项目实际上是由许多的“代码版段”组成的: 使用less.sass等一些预处 ...
- HTML表格布局
1 浏览器:接受浏览者的操作,然后帮浏览者去web服务器请求网页内容,然后展现成人人眼能够看得懂的可视化页面的软件. 2 IE是浏览器的一种.<ietest工具& ...
- cannot import name '_imaging' from 'PIL'
学习廖雪峰官网的Python的教程,在常用的第三方模块的Pillow的学习过程中总是报错cannot import name '_imaging' from 'PIL' 解决办法: 1.下载并安装An ...
- 基于Verilog的带FIFO输出缓冲的串口接收接口封装
一.模块框图及基本思路 rx_module:串口接收的核心模块,详细介绍请见“基于Verilog的串口接收实验” rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能 ...
- AOP的第一个小坑
今天看项目源码,看到Service类继承了一个SelfProxy类,这个类实现了一个叫self()的方法,用于返回动态代理生成的实例. 为什么要返回实例呢,因为有的时候类内部需要调用自身的public ...
- fabric一些资料网站,长期更新
nodejs的入门教程 http://nqdeng.github.io/7-days-nodejs/#1.2 http://blog.fens.me/series-nodejs/ fabric的知识博 ...
- Ubuntu下useradd与adduser区别
Ubuntu下useradd与adduser有所不同 1.useradd在使用该命令创建用户是不会在/home下自动创建与用户名同名的用户目录,而且不会自动选择shell版本,也没有设置密码,那么这个 ...
- Power BI 关注博客更新
原本当你访问你常用的数据库时候,该库的新增,修改,删除,通过PowerBI都很容易发现,但是在Web上面,通过PowerBI来发现Web修改就没那么容易了. 现在,我想通过PowerBI的报告来显示某 ...
- jQuery-3.事件篇---键盘事件
jQuery键盘事件之keydown()与keyup()事件 鼠标有mousedown,mouseup之类的事件,这是根据人的手势动作分解的2个触发行为.相对应的键盘也有这类事件,将用户行为分解成2个 ...