python基础之模块(一)

概述

模块,用一砣代码实现了某个功能的代码集合。一个功能可能由 N 个函数来组成,这些函数写到一个py文件中,那么这个Py文件就是传说中的模块.

模块可将代码归类,让你的代码看着条理清晰,当然还需要你在提前设计程序时的设计思路清晰,更多的调用,慢慢练吧,骚年!

模块使用时的特点:

  1. 先导入,后使用
  2. 模块可为目录,也可为py文件

模块分为三类:

  • 内置模块
  • 第三方模块
  • 自定义模块

自定义模块

自定义模块顾名思义就是自己编写的对某功能实现的一些函数集合.

模块的导入

模块导入的方式比较多:

import index  #执行py与index在同一目录
from index import func1   #执行py与index在同一目录,func1为index.py中的某个函数

又比如,有某个目录:

|____1.py
|____2.py
|______pycache__
| |____geno.cpython-35.pyc
|____db
|____digui.py
|____geno.py
|____iter_test.py
|____lib
| |______pycache__
| | |____commands.cpython-35.pyc
| |____commands.py

1.py想导入lib/commands.py文件中的东西,commands是一个模块,我们可以这么做:

from lib import commands  #导入
commands.func1	#调用func1函数
	#也可以这么用
from lib.commands import * 
func1   #直接调用

那么问题来了,不同目录之间怎么调用呢?

.
|______init__.py
| |____a
| | |____22.py
| | |______init__.py
| | |______pycache__
| | | |______init__.cpython-35.pyc
| | | |____test.cpython-35.pyc
| | |____test.py
| |____b
| | |____1.py

b/1.py 想调用a/22.py 模块,这就需要添加环境变量来调用了

import sys
sys.path.append('..')

但这么搞是不是有点太low了,来个比较高档点吧:

import sys,os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

为毛这么搞可以?来解释下:

  • file 获取当前文件以及所在的位置,但有可能得到的是相对路径
  • os.path.abspath() 获取文件的绝对路径
  • os.path.dirname() 获取文件的上级目录

这里需要插播一下python自动创建的全局变量:

  • file 获取当前文件以及所在的位置,但有可能得到的是相对路径
  • name 如果模块被导入,那么__name__的名字就为模块的名字,如果模块是被直接执行,__name__的值为’main
  • main 仅仅是用来检测该文件代码是否是主程序文件,也即非模块。通常可以用来测试模块比如你可以通过检测来执行一些测试用例,但当文件作为模块导入其他程序中时,检测__main__会为False,即里面的代码不会执行
  • doc 获取文件的注释
  • cached 字节码的路径
  • package 一般使用方式:print(xxx.package),显示xxx模块的文件路径

内置模块

sys模块

来看一个比较好玩的进度条吧,装逼器:

import sys,time
def view_bar(num,totle):
    rate=num/totle
    rate_num=int(rate*100)
    r='
%s>%d%%'%('='*num,rate_num)
    sys.stdout.write(r)
    sys.stdout.flush()

if __name__ == '__main__':
    for i in range(101):
        time.sleep(0.1)
        view_bar(i,100)

sys比较简单,主要用来提供对python解释器的操作.

sys.argv           #命令行参数List,第一个元素是程序本身路径
sys.exit(n)        #退出程序,正常退出时exit(0)
sys.version        #获取Python解释程序的版本信息
sys.maxint         #最大的Int值
sys.path           #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       #返回操作系统平台名称
sys.stdin          #输入相关
sys.stdout         #输出相关
sys.stderror       #错误相关

os模块

提供对操作系统进行调用的接口:

os.getcwd()                 #获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")         #改变当前脚本工作目录;相当于shell下cd
os.curdir                   #返回当前目录: ('.')
os.pardir                   #获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2')    #可生成多层递归目录
os.removedirs('dirname1')   #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')         #生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')         #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')       #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()                 #删除一个文件
os.rename("oldname","new")  #重命名文件/目录
os.stat('path/filename')    #获取文件/目录信息
os.sep                      #操作系统特定的路径分隔符,win下为"\",Linux下为"/"
os.linesep                  #当前平台使用的行终止符,win下为"	
",Linux下为"
"
os.pathsep                  #用于分割文件路径的字符串
os.name                     #字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")   运行shell命令,直接显示
os.environ                  #获取系统环境变量
os.path.abspath(path)       #返回path规范化的绝对路径
os.path.split(path)         #将path分割成目录和文件名二元组返回
os.path.dirname(path)       #返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)      #返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)        #如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)         #如果path是绝对路径,返回True
os.path.isfile(path)        #如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)         #如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  #将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)      #返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)      #返回path所指向的文件或者目录的最后修改时间
os.getlogin()            #获取当前登录用户

重点说下os.path.join()的用法:
一般是在拼接路径的时候用的。举个例子

os.path.join(“home”, "me", "mywork")
在Linux系统上会返回
“home/me/mywork"
在Windows系统上会返回
"homememywork"
好处是可以根据系统自动选择正确的路径分隔符"/"或""

之前博客中有写一篇判断文件是否存在的模块,链接在这:
点我点我点我

hashlib

用于加密相关的操作,替代了MD5和SHA,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
看下例子:

import hashlib
obj=hashlib.md5(bytes('asdfasdf',encoding='utf8'))  #1
obj.update(bytes('123',encoding='utf8'))
res=obj.hexdigest()
print(res)

1位置有一个'hashlib.md5(bytes('asdfasdf',encoding='utf8'))',干啥用的呢?因为如果碰到撞库攻击的时候,对方会用的密码字典去匹配你的密码,所以我们在前面加上自己的字段,这样生成的md5值肯定和对方的不一样了!

之前博客中有一篇说了下一个密码加密的东西,链接:
点我点我点我

random模块

随机模块,比较简单,不多做说明了.
之前博客中有一篇随机生成验证码的模块,链接在这:
点我点我点我

序列化模块

Python中序列化数据的模块有两个:

  1. json 用于【字符串】和 【python基本数据类型】 间进行转换
  2. pickle 用于【字符串】和 【python基本数据类型】 间进行转换

其实无非是load/dump/loads/dumps的应用

json 和 pickle 区别

  1. json 更适合夸语言操作,字符串,基本数据类型操作

  2. pickle 适合所有类型的序列化 python 操作,pickle 仅适用于 python,2和3可能不兼容

json

通过 json.loads 反序列化时,一定要注意双引号,要与其他语言格式相匹配了

之前博客写过一片json的使用,链接:
点我点我

pickle

大体类似,上个例子吧,需要注意的一点就是二进制文件的读写模式:

import pickle
li=[1,2,3,4,5,'cc']
####pickle.dump(li,open('db','wb'))
r=pickle.dumps(li)
print(r)
res=pickle.loads(r)
print(res)

out:

b'x80x03]qx00(Kx01Kx02Kx03Kx04Kx05Xx02x00x00x00ccqx01e.'
[1, 2, 3, 4, 5, 'cc']

requests模块

Requests 是一个第三方的库,是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,变得美好了许多,使用Requests可以轻而易举的完成浏览器可有的任何操作。要比urllib模块强大.

安装很简单: pip3 install requests

配合json可以玩个有意思的天气查询:

import json,requests

response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京')
response.encoding='utf-8'

dic=json.loads(response.text) #text 指 requests生成的内容
print(dic)

out:

{'desc': 'OK', 'data': {'wendu': '20', 'forecast': [{'fengxiang': '无持续风向', 'date': '14日星期二', 'low': '低温 18℃', 'high': '高温 24℃', 'fengli': '微风级', 'type': '雷阵雨'}, {'fengxiang': '无持续风向', 'date': '15日星期三', 'low': '低温 17℃', 'high': '高温 30℃', 'fengli': '微风级', 'type': '多云'}, {'fengxiang': '无持续风向', 'date': '16日星期四', 'low': '低温 20℃', 'high': '高温 33℃', 'fengli': '微风级', 'type': '多云'}, {'fengxiang': '无持续风向', 'date': '17日星期五', 'low': '低温 22℃', 'high': '高温 33℃', 'fengli': '微风级', 'type': '多云'}, {'fengxiang': '无持续风向', 'date': '18日星期六', 'low': '低温 21℃', 'high': '高温 31℃', 'fengli': '微风级', 'type': '多云'}], 'yesterday': {'fx': '无持续风向', 'date': '13日星期一', 'low': '低温 18℃', 'high': '高温 22℃', 'fl': '微风', 'type': '雷阵雨'}, 'city': '北京', 'ganmao': '各项气象条件适宜,无明显降温过程,发生感冒机率较低。', 'aqi': '45'}, 'status': 1000}

time模块

时间相关的操作,有time,datetime两个模块.

python中的时间表示,有三种方式:

  1. 1970年1月1日之后的秒,即:time.time()
  2. 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d')
  3. 结构化时间 是一个元组数据,元组包含了:年、日、星期等... time.struct_time 即:time.localtime()
import time
import datetime
 
print(time.time()) #返回当前系统时间戳
print(time.ctime()) #输出Tue Jan 26 18:23:48 2016 ,当前系统时间
print(time.ctime(time.time()-86640)) #将时间戳转为字符串格式
print(time.gmtime(time.time()-86640)) #将时间戳转换成struct_time格式
print(time.localtime(time.time()-86640)) #将时间戳转换成struct_time格式,但返回本地时间
print(time.mktime(time.localtime())) #与time.localtime()功能相反,将struct_time格式转回成时间戳格式
time.sleep(4) #常用,用来暂停
print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将struct_time格式转成指定的字符串格式
print(time.strptime("2016-01-28","%Y-%m-%d") ) #将字符串格式转换struct_time格式
 
################################
 
print(datetime.date.today()) #输出格式 2016-01-26
print(datetime.date.fromtimestamp(time.time()-864400) ) #2016-01-16 将时间戳转成日期格式
current_time = datetime.datetime.now() #
print(current_time) #输出2016-01-26 19:04:30.335935
print(current_time.timetuple()) #返回struct_time格式

###############################################
 
"""datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])"""

print(current_time.replace(2014,9,12)) #输出2014-09-12 19:06:24.074900,返回当前时间,但指定的值将被替换
############################################
str_to_date = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #将字符串转换成日期格式
new_date = datetime.datetime.now() + datetime.timedelta(days=10) #比现在加10天
new_date = datetime.datetime.now() + datetime.timedelta(days=-10) #比现在减10天
new_date = datetime.datetime.now() + datetime.timedelta(hours=-10) #比现在减10小时
new_date = datetime.datetime.now() + datetime.timedelta(seconds=120) #比现在+120s

具体时间的表示方式:

%Y  Year with century as a decimal number.
%m  Month as a decimal number [01,12].
%d  Day of the month as a decimal number [01,31].
%H  Hour (24-hour clock) as a decimal number [00,23].
%M  Minute as a decimal number [00,59].
%S  Second as a decimal number [00,61].
%z  Time zone offset from UTC.
%a  Locale's abbreviated weekday name.
%A  Locale's full weekday name.
%b  Locale's abbreviated month name.
%B  Locale's full month name.
%c  Locale's appropriate date and time representation.
%I  Hour (12-hour clock) as a decimal number [01,12].
%p  Locale's equivalent of either AM or PM.

看起来复杂吧,来张图吧,应该就清楚了:

logging模块

logging用于记录日志且线程安全的模块.

日志level的分类:

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

但文件日志记录

import logging
logging.basicConfig(filename='log.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10) 
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')

需要注意一点:只有【当前写等级】大于【日志等级】时,日志文件才被记录

format格式中的一些说明:

属性 格式化 描述
args 将参数的元组合并进消息产生消息,或者将字典中对应的值合并为消息
asctime %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
created %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
exec_info 异常信息
filename %(filename)s 调用日志输出函数的模块的文件名
funcName %(funcName)s 调用日志输出函数的函数名
levelname %(levelname)s 文本形式的日志级别
levelno %(levelno)s 数字形式的日志级别
module %(module)s 调用日志输出函数的模块名
msecs %(msecs)d 创建日志时的毫秒时间
message %(message)s 用户输出的消息
msg 传入的格式化字符串
name %(name)s logger的名字
pathname %(pathname)s 调用文件的路径
process %(process)d 调用日志系统的进程ID
processNmae %(processNmae) 进程名字
thread %(thread)d 线程
threadName %(threadName)s 线程名称

那么多文件的写入日志需要怎么搞呢?

日志如果要模块化时,需要有4个知识点:

  • logger 创建一个在应用程序中用到的接口
  • handler 处理器,将logger产生的日志,发送给对应的文件
  • filter 过滤器,用来将符合条件的日志过滤出来
  • formatter 输出前格式化日志,形成你想要的格式的日志
import logging
 
######## create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
 
 
######## create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
 
######## create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)

######## create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
######## add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
 
######## add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)

调用方式:

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

解释下上面的代码:

  1. 创建一个logger接口
  2. 创建显示终端或文件,并设置日志级别
  3. 创建日志格式标准
  4. 格式标准添加至显示终端
  5. 将终端的handler添加至logger

之前博客写过一篇日志处理的模块,链接:
点我点我点我

原文地址:https://www.cnblogs.com/ccorz/p/5584183.html