包
什么是包: --- 文件夹下具有__init__.py 文件就是一个包
推荐使用 from . import
包的导入;
from ss.bake.API.policy import func --- 绝对导入
from ..API.www import ww ww()--- 相对路径导入 必须在外部使用
注意点:
使用相对路径必须在最外层报的同级进行导入
python2 中 import 包, 如果包没有__init__.py 会报错, ython3 中没有__init__.py 不会报错
只要文件夹下含有__init__.py 文件就是一个包, 包是干什么的呢?
回想一下, 之前我们没有学习模块的时候将一个整体的功能写入到文件中, 为了能够充分的将某个功能进行重用 我们使用了模块, 但是慢慢的模块就会越来越多. 我们想提高程序的结构性可维护性, 就使用包将模块进行统一管理
包能够管理多个模块, 我们想要使用包里的模块怎么办呢?
使用 import 和 from xx import xx 现有如下结构
bake
├── __init__.py
├── API
├── __init__.py
├── policy.py
└── versions.py
├── cmd
├── __init__.py
└── manage.py
└── db
├── __init__.py
└── models.py
我们在 bake 同级创建一个 test.py 进行导入 policy.py 我们使用模块的 import 的时候只能将 API 添加到 sys.path 的路劲中, 我们来看看包使用 import 导入
- import bake.API.policy
- bake.API.policy.get()
导入的太长了下边使用的时候还需要在重复写一遍, 我们可以使用 as 起别名
- import bake.API.policy as p
- p.get()
这样的操作只支持包, 普通的文件夹无效, 有人一定在想我把 bake 拿过来然后一层一层的打开那拿工具就可以了
- import bake
- bake.API.policy.get()
不好使, 这样导入是只将 policy 导入了, 有人想怎么将 API 包下的模块全部导入不要急, 先说单独导入的方式
咱们能够使用 import 进行导入, 在来看看 from 的导入方式
- from bake.API import policy
- policy.get()
- from bake import API
- print(API.versions.name)
还是不好使, 通过这两个我们能够感觉都导入的时候指定要导入的内容, 不能再导入后在进行开箱子
我们现在说了单独导入一个模块, 现在来说道说道怎么导入某个包下的所有模块, 想要导入某个包下的所有的模块 我们就需要在包中的__init__.py 做点手脚
bake 包下的__init__.py
from . import API
. 是当前路径, 因为 from 的时候不能空着
API 包下的__init__.py
from . import policy
我们将包下的__init__配置好, 然后在 test.py 进行导入
- import bake
- bake.API.policy.get()
又好使了, 这是为什么呢? 我们 import 导入 bake 这个包, 因为 bake 是一个文件夹不能进行任何操作, 就让__init__.py 代替它 去将 API 这包中的模块导入, API 也是一个文件夹不能操作就需要让 API 下边的__init__.py 去找 API 下边的两个模块
这个和公司的上下级关系一样, 打比方现在 test.py 就是一个 ceo 要和 policy 这个小员工谈话, ceo 先把这个想法人事经理, 人事经理就是 bake 这个包, 人事经理通知人事让人事查找一下 policy 在那个部门, 人事查到后通知部门的负责人, 部门的负责人在通知部门的主管, 主管告诉 policy 这个员工, 说 ceo 要找你, 部门的主管带着 policy 去找人事, 人事带着 policy, 人事然后在带着 policy 去找 ceo. 最后成功的和 ceo 进行了一番交流
如果在传达的时候中间一个环节忘记传递了, policy 就不知道 ceo 在找他, ceo 等了好久不来 ceo 就生气报错了
使用的时候需要注意: 有的同学, 想在 policy 文件中导入 versions 就是直接使用 import, 在 policy 文件使用没有问题, 很美, 很高兴. 但是在 test.py 执行的时候就会报错 因为我们在 test.py 中执行的 import versions 相当于在 test.py 文件进行查找, 肯定不会找到, 我们需要在 policy 文件中向 sys.path 添加了当前的路劲就可以了 具体操作如下:
- import os
- import sys
- sys.path.insert(os.path.dirname(__file__)
__file__获取的是当前文件的路径, 这样我们就能在 test 中正常使用了, 我们使用 from 也能够将某个包下所有的模块全都导入 比如我们现在想将 cmd 包下的所有的模块导入需要在 bake 包下的 init.py 进行设置
from . import *
我们需要在 API 包下设置__init__.py
__all__ = ["policy","versions"]
或
- from . import policy
- from . import versions
我们需要在 db 包下设置__init__.py
__all__ = ["models"]
或
from . import models
我们需要在 cmd 包下设置__init__.py
__all__ = ["manage"]
或
from . import manage
以上两种推荐使用下 from . import manage 灵活, 可读性高
test.py 调用如下:
- from bake.API import *
- print(versions.name)
- policy.get()
- from bake.db import *
- models.register_models(123)
- from bake.cmd import *
- print(manage.name)
在使用 import 有个注意点, python2 中如果 import 包, 没有__init__.py 文件就会报错 python3 import 没有__init__.py 文件的包不会报错 from 包 import 包或者模块(在 import 后边不能在进行. 操作)
路径: 绝对路径: 从最外层 (bake) 包. 查找的就是绝对路径 相对路径:. 就是相对路径, .. 是上一级目录 例如: 我们在 bake/API/version.py 中想要导入 bake/cmd/manage.py
- # 绝对路径:
- from bake.cmd import manage
- manage.main()
- # 相对路径:
- from ..cmd import manage
- manage.main()
注意在使用相对路径的时候一定要在于 bake 同级的文件中测试 我们需要在和 bake 同级的 test.py 中测试
from bake.cmd import manage
logging 日志
我们来说一下这个 logging 模块, 这个模块的功能是记录我们软件的各种状态, 你们现在和我一起找到红蜘蛛的那个图标, 然后右键找一找是不是有个错误日志. 其实每个软件都是有错误日志的, 开发人员可以通过错误日志中的内容对他的程序进行修改
这只是一种应用场景, 有的还会将日志用于交易记录. 比如你给我转账应该做记录吧,
我们使用的信用卡, 每消费的一笔都会记录, 我们来看看这个日志怎么用?
我们先来看一下函数式简单配置
- import logging
- logging.debug('debug message')
- logging.info('info message')
- logging.warning('warning message')
- logging.error('error message')
- logging.critical('critical message')
默认情况下 Python 的 logging 模块将日志打印到了标准输出中, 且只显示了大于等于 WARNING 级别的日志, 这说明默认的日志级别设置为 WARNING
(日志级别等级 CRITICAL> ERROR> WARNING> INFO> DEBUG),
默认的日志格式为日志级别: Logger 名称: 用户输出消息.
我们自己用函数写的这个可以正常使用但是不够灵活, 我们看看这个灵活的
灵活配置日志级别, 日志格式, 输出位置:
- import logging
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
- datefmt='%a, %d %b %Y %H:%M:%S',
- filename='test.log',
- filemode='w')
- logging.debug('debug message')
- logging.info('info message')
- logging.warning('warning message')
- logging.error('error message')
- logging.critical('critical message')
basicConfig()函数中可通过具体参数来更改 logging 模块默认行为, 可用参数有:
filename: 用指定的文件名创建 FiledHandler, 这样日志会被存储在指定的文件中.
filemode: 文件打开方式, 在指定了 filename 时使用这个参数, 默认值为 "a" 还可指定为 "w".
format: 指定 handler 使用的日志显示格式.
datefmt: 指定日期时间格式.
level: 设置记录日志的级别
stream: 用指定的 stream 创建 StreamHandler. 可以指定输出到
sys.stderr,sys.stdout 或者文件(f=open('test.log','w')), 默认为 sys.stderr. 若同时列出了 filename 和 stream 两个参数, 则 stream 参数会被忽略.
format 参数中可能用到的格式化串:
%(name)s Logger 的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名, 可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间, 用 UNIX 标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的, 自 Logger 创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间. 默认格式是 "2003-07-08 16:49:45,896". 逗号后面的是毫秒
%(thread)d 线程 ID. 可能没有
%(threadName)s 线程名. 可能没有
%(process)d 进程 ID. 可能没有
%(message)s 用户输出的消息
logger 对象配置
- import logging
- logger = logging.getLogger()
- # 创建一个 handler, 用于写入日志文件
- fh = logging.FileHandler('test.log',mode="a",encoding='utf-8')
- # 再创建一个 handler, 用于输出到控制台
- ch = logging.StreamHandler() #屏幕
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(filename)s-[line:%(lineno)d]%(levelname)s - %(message)s')#-- 将屏幕和文件都用以上格式
- fh.setLevel(logging.DEBUG)# 设置记录级别
- fh.setFormatter(formatter)
- # 使用自己定义的格式化内容
- ch.setFormatter(formatter)
- logger.addHandler(fh) #logger 对象可以添加多个 fh 和 ch 对象
- logger.addHandler(ch)
- logger.debug('logger debug message')
- logger.info('logger info message')
- logger.warning('logger warning message')
- logger.error('logger error message')
- logger.critical('logger critical message')
logging 库提供了多个组件: Logger,Handler,Filter,Formatter.Logger 对象提供应用程序可直接使用的接口, Handler 发送日志到适当的目的地, Filter 提供了过滤日志信息的方法, Formatter 指定日志显示格式. 另外, 可以通过: logger.setLevel(logging.Debug)设置级别, 当然, 也可以通过
fh.setLevel(logging.Debug)单对文件流设置某个级别.
来源: http://www.bubuko.com/infodetail-3139833.html