模块的本质就是一个.py
文件。
导入和调用模块:import module_name
>>> module_name.method(args)
python中有三种模块:
1. 内置模块(内置于解释器中,不用导入,直接调用)
2. 第三方模块(在lib目录下,导入后可以调用)
3. 自定义模块(默认从当前工作目录下导入,导入后可以调用)
python解释器对于模块的查找也是遵循上面的顺序。python模块丰富,后期要学的网络编程和线程进程,基本就是在学socket
和threading processing
这两个模块。
时间也是一种数据类型,能被计算机计算。时间的三种表示:
- 时间戳(time stamp):一个浮点型数字,定义1970年UNIX诞生的那天为0,往后的时间相对于它加秒表示。time.time()
返回当前的时间戳
- 结构化时间(structure time):time.localtime()
默认传入当前的时间戳作参数,返回一个元组形式的结构时间对象。tips: 只要是对象,都有.method() ,这样我们就能拿到这个对象的元信息。
```
import time
print(time.localtime())
res = time.localtime() # 返回一个对象
print(res.tm_year, res.tm_mon, res.tm_mday, res[3], res[4]) # 拿到对象的元信息
# 结果如下:
# time.struct_time(tm_year=2017, tm_mon=6, tm_mday=21, tm_hour=14, tm_min=13, tm_sec=12, tm_wday=2, tm_yday=172, tm_isdst=0)
# 2017 6 21 14 13
```
'2016-06-21'
time.mktime(time.localtime())
time.localtime()
时间戳>>>结构化。默认传入当前时间戳。time.strftime('%Y-%m-%d, time.localtime())
time.strptime('2016-06-21', '%Y-%m-%d')
time.asctime()
默认把当前结构时间转化为字符串time.ctime()
默认把当前时间戳转化为字符串random.random()
返回[0~1]之间的浮点数random.randint(x, y)
返回[x, y]之间的整数,左右包含。random.randrange(1, 3)
返回[1, 3)之间的整数,左包含random.choice([1, 2, 4, 'hello'])
随机取列表中的一个元素random.sample([1, 2, 3 , 4, 'abc'], n)
随机取列表中的n个元素random.uniform(x, y)
随机取[x~y]之间的浮点数,比random.random方便一点,可以自定义范围random.shuffle(序列)
随机打乱一个序列import random
# 定义一个函数,能生成数字字母大小写混合的n位验证码
def generate_val(n):
val = '' #定义验证码为空字符串
for i in range(n):
num = str(random.randint(0, 9))
str1 = chr(random.randint(65, 90)) # 大写字母的范围
str2 = chr(random.randint(91, 122)) # 小写字母的范围
e = random.choice([num, str1, str2]) # #随机选择以上
val += e #拼接结果
return val
print(generate_val(5)) # 随机生成5位的字符串:fE7s0
import hashlib
md5 = hashlib.md5() # 先得到一个md5对象(名字随意)
md5.update(b'my world') # 作摘要处理。注意,在python3中,要加b将字符串转为字节
md5.hexdigest() # 返回对象的十六进制摘要:c616b851b09d26c698ed5bcaf7c80514
操作系统提供API,供python解释器调用,实现对硬件的操作。
sys模块处理和python解释器运行相关的参数。
用命令行终端启动解释器时,传递给脚本的所有参数都由argv接收,以列表的形式保存。列表的第一个元素sys.argv[0]
是脚本自身的名称。
我们新建一个Modules.py文件,写入如下内容:
import sys
print('script name is', sys.argv[0])
if len(sys.argv) > 1:
print('there are', len(sys.argv)-1, 'arguments:')
print([arg for arg in sys.argv])
else:
print('there are no arguments')
现在在终端用解释器执行这个脚本:
我们继续在文件中再添加一个用户登录验证,用户名和密码的值通过启动解释时,用参数的方式传递进去:
import sys
print('script name is', sys.argv[0])
if len(sys.argv) > 1:
print('there are', len(sys.argv)-1, 'arguments:')
print([arg for arg in sys.argv])
else:
print('there are no arguments')
user = sys.argv[1]
pwd = sys.argv[2]
if user == 'ayhan' and pwd =='123':
print('login ok')
再次在终端启动解释器来执行脚本,并传入用户名和密码这两个参数:
也可以添加更多参数-u, -p 来提示用户名和密码:
import sys
user = sys.argv[sys.argv.index('-u')+1]
pwd = sys.argv[sys.argv.index('-p')+1]
if user == 'ayhan' and pwd == '123':
print('login ok')
sys.path的内容是路径列表,解释器在搜索模块时,是按照该列表中的路径来搜索的。我们可以修改这个列表的内容,以添加任何位置的自定义模块:
import sys
print('path has',len(sys.path),'members: ')
print(sys.path)
sys.path.insert(0, r'D:\Mymodule') # 插入自定义的目录到模块查找路径列表
print('- '*20)
print('path has',len(sys.path),'members')
print(sys.path)
exit(0) 正常退出程序,不同于break,后者是退出本层循环,继续执行下面的代码。
def logger():
my_logger = logging.getLogger() # 创建一个logger实例 print(my_logger.__class__) >>>
fh = logging.FileHandler('/d:test.log') # 创建FileHandler 的实例,用于写入到日志文件
ch = logging.StreamHandler() # 创建StreamHandler的实例,用于输出到控制台
my_format = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
fh.setFormatter(my_format) # 大鱼吃小鱼,小于吃虾米
fh.setLevel(logging.DEBUG)
ch.setFormatter(my_format)
ch.setLevel(logging.DEBUG)
my_logger.addHandler(fh)
my_logger.addHandler(ch)
my_logger.setLevel(logging.DEBUG)
my_logger.debug('debug...')
my_logger.info('info...')
my_logger.warning('warning...')
my_logger.error('error...')
my_logger.critical('ciritical...')
logger()
序列化和反序列化的概念:
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化。
虚拟机状态的挂起和恢复就是序列化和反序列化的过程。
json是一种标准的序列化格式,速度快,易读,兼容性好。
import json # 导入json模块
d = {'a': 1, 'b': 2, 'c': 3} # 定义一个字典
d_json = json.dumps(d)
print(d_json, type(d_json))
with open('json_test.txt','w') as f:
f.write(d_json) # 将字典在内存中的数据序列化为json标准格式的字符串,写入文件中保存起来。
with open('json_test.txt', 'r')as f:
d_new = json.loads(f.read()) # 从磁盘读取son标准格式的字符串,反序列化到内存
print(d_new,type(d_new))
"""
sort_keys=True :根据key排序
indent=4 :缩进,阅读效果友好
ensure_ascii:False:序列化非ascii码时就不会出现显示问题了。
"""
res = json.dumps(data_obj, sort_keys=True, indent=4, ensure_ascii=False)
print(res)
with open('data.json','w',encoding='utf-8')as f:
f.write(res)
注意,json序列化后的字符串格式与python对象的格式有细微的区别:
另外,只要是按照json格式写的文本,都可以直接反序列化。
picke的用法形式与json一样,只能用于python,但可以序列化任何python数据类型。另外pickle写入的是bytes,所以写入方式为wb
读取方式为rb
。
网络编程经常使用该模块。
调用系统命令,产生一个新进程,与原进程并行运行。
import subprocess
print(subprocess.__file__) # 可以查看导入的模块完整路径,以确定是否是和自定义模块重名了。
# 调用windows下的命令,dir相当于linux下的ls, findstr相当于linux下的grep; 下面拿到两个子进程对象。
s1 = subprocess.Popen(r'dir D:\Pythonworks', shell=True, stdout=subprocess.PIPE)
s2 = subprocess.Popen('findstr, a*', shell=True, stdin=s1.stdout, stdout=subprocess.PIPE)
s2.wait() # 子进程执行完,再执行主进程print
print(s2.stdout.read().decode('gbk'))
# 进程间借助PIPE通信(把输出的信息放到pipe里,不输出到屏幕)主进程'print'最终读取进程's2'的结果,打印出来。
# subprocess模块使用当前系统默认编码,拿到的是gbk编码的bytes,所以要用gbk解码。
import configparser
cfg = configparser.ConfigParser() # 创建对象
cfg.read('test.ini', encoding='utf-8') # 读取文件内容到对象
print(cfg.sections()) # 获取对象所有标题(DEFAULT除外)。
# 注意:配置文件中的DEFAUL标题是默认关键字,用来存放其它标题下的共有信息。
print(cfg.items('DEFAULT')) # 获取标题下的键值对,这里以'DEFAULT'标题为例,也可以是文件中的任何标题
print(cfg.options('bitbucket.org')) # 获取标题下的键
print(cfg.get('bitbucket.org', 'User')) # 获取标题下键对应的值:可根据值的具体类型来选择以下方法:
# .get(字符串格式) .getint(整型格式) .getboolean(布尔值格式) .getfloat(浮点型格式)
'''
打印结果如下:
['bitbucket.org', 'topsecret.server.com']
[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes')]
['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
hg
'''
cfg.has_section('bitbucket.org') # 检查是否存在该标题,返回True/False
cfg.has_option('bitbucket.org','user') # 检查该标题下是否存在这个键,返回True/False
cfg.add_section('admin') # 添加标题(已存在会报错)
cfg['admin']['name']='ayhan' # 标题下添加键值对
cfg['admin']['age']='18'
cfg.write(open('test.ini','w')) # 将修改后的对象写入文件
cfg.set('admin','age','28') # 修改值
cfg.write(open('test.ini','w'))
cfg.remove_section('topsecret.server.com') #删除标题
cfg.remove_option('DEFAULT','Compression' ) # 删除标题下的键
cfg.write(open('test.ini','w'))
按照configparser的格式,我们也可以自行创建一个类似的配置文件:
import configparser
cfg = configparser.ConfigParser() # 创建对象
cfg['DEFAULT'] = {'school': 'oldboy', # 为对象添加标题及键值信息
'major': 'python'}
cfg.add_section('student1')
cfg.add_section('student2')
cfg['studnet3']={'name': 'Tom'} # 添加标题也可以用字典的形式
cfg['student1']['name']='Seb'
with open('mycfg.ini','w')as f: # 对象写入文件
cfg.write(f)