Module

Module

模块

在Python中:一个.py文件就称之为一个模块(Module)

分类

但其实import加载的模块分为四个通用类别:

  • 内置标准模块(又称标准库)执行help('modules')查看所有Python自带模块列表
  • 第三方开源模块,可通过pip install 模块名 联网安装
  • 自定义模块
优点

是用模块最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。现在,假设我们的abc和xyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突方法是选择一个顶层包名,比如mycompany,按照如下目录>>>存放引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz。
请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。init.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。

自己创建模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了sys模块,自己的模块就不可命名为sys.py,否则将无法导入系统自带的sys模块。

此处是深坑!请注意!详见Python踩坑指南:
https://blog.csdn.net/Viper__s/article/details/80935996

模块调用
import module

from module import xxxx

from module.xx.xx import xx as rename

from module.xx.xx import *

注意:模块一旦被调用,即相当于执行了另外一个py文件里的代码

自定义模块

这个最简单,创建一个.py文件,就可以称之为一个模块,就可以在另外一个程序里导入

模块查找路径
import sys

print(sys.path)

# ['C:\\Python\\Object Oriented', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36', 'C:\\Python36\\lib\\site-packages']

Python解释器会按照列表表顺序依次到每个目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立即导入,不在继续往后找
注意:列表的第一个元素为空,即代表当前目录,所以你自定义的模块在当前文件会被优先导入

开源模块额安装,使用

https://pypi.python.org/pypi
待更新

待更新

跨模块导入

待更新

绝对导入&相对导入

待更新

序列化(json&pickle)

把变量从内存中变成可存储或传输的过程称之为序列化>>>
在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening 等等,都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
序列化的目的:

1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性。

Python 提供了pickle 模块来实现序列化。首先,我们尝试把一个对象序列化并写入文件:

import pickle
from typing import Dict

d = dict(name='linga', age=18, hobby='football')
d_dumps = pickle.dumps(d)
print(pickle.dumps(d_dumps))
# b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00lingaq\x02X\x03\x00\x00\x00ageq\x03K\x12X\x05\x00\x00\x00hobbyq\x04X\x08\x00\x00\x00footballq\x05u.'

d_loads = pickle.loads(d_dumps)
print(d_loads)
# {'name': 'linga', 'age': 18, 'hobby': 'football'}

json:用于字符串和Python数据类型间in行转换
pickle:用于Python特有的类型和Python的数据类型间进行转换
json,pickle两个都有四个模块:
dump,load:单个数据读写一个文件
dumps,loads:用于网络传输,多个数据读写一个文件

import pickle
data = {"k1": 123, "k2": "hello"}
# pickle.dumps将数据通过特殊的形式转换为只有Python语言认识的字符串
p_str = pickle.dumps(data)
print(p_str)


# pickle.dumps将数据通过特殊的形式转换为只有Python语言认识的字符串,并写入文件
with open('test.pk','wb') as fh:
    pickle.dumps(data,fh)
  
    
import json


# json.dumps将数据通过特殊的形式转换为所有编程语言都认识的字符串
j_str = json.dumps(data)
print(j_str)


# json.dumps将数据通过特殊的形式转换为所有编程语言都认识的字符串,并写入文件
with open('test.pk','wb') as fh:
    json.dumps(data,fh)

通过下面这段代码详细了解下json的四个方法的使用:
常规用法:

import json
l1 = ['张三','历史','王五','alex','老土','旭哥']

# dump load 有关文件存储
f = open('json_file',encoding='utf-8',mode='w')
json.dump(l1,f,ensure_ascii=False)  # 将序列化的字符串存储到文件中
f.close()

f = open('json_file',encoding='utf-8')
ret = json.load(f)
print(ret,type(ret))
f.close()

文件操作相关:

import json


dic = {"alex": ('women','women','老女人')}
dic2 = {"alex1": ('women','women','老女人')}
dic3 = {"alex2": ('women','women','老女人')}

with open("json_module", mode='w', encoding='utf-8') as fh:
    json.dump(dic, fh, ensure_ascii=False)
    json.dump(dic2, fh, ensure_ascii=False)
    json.dump(dic3, fh, ensure_ascii=False)

f = open('json_module', encoding='utf-8',)
print(json.load(f))
print(json.load(f))
print(json.load(f))
f.close()

执行后

C:\Python36\python.exe C:/Python/Module/json_module.py
Traceback (most recent call last):
  File "C:/Python/Module/json_module.py", line 14, in <module>
    print(json.load(f))
  File "C:\Python36\lib\json\__init__.py", line 299, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "C:\Python36\lib\json\__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "C:\Python36\lib\json\decoder.py", line 342, in decode
    raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 36 (char 35)

将多个序列化的字符串写入文件,然后反序列化,就会出错,用dump,load只能写入和读取文件:一个序列化的字符串
这里的dump直接将一个文件序列化成一个字符串,而反序列化时按照之前的文件操作一行一行的读取.
如果说一定要这样实现的话看下面这段代码:

import json


dic = {"alex": ('women', 'women', '老女人')}
dic2 = {"alex1": ('women', 'women', '老女人')}
dic3 = {"alex2": ('women', 'women', '老女人')}

with open('json_files', encoding='utf-8', mode='a') as f1:
    s1 = json.dumps(dic, ensure_ascii=False)        # ensure_ascii=False:可以看到写入的
    f1.write(s1+'\n')
    s2 = json.dumps(dic2, ensure_ascii=False)
    f1.write(s2+'\n')
    s3 = json.dumps(dic3, ensure_ascii=False)
    f1.write(s3+'\n')

with open('json_files', encoding='utf-8') as f2:
    for line in f2:
        dic = json.loads(line)
        print(dic, type(dic))

dic = {"alex": ('women','women','老女人')}
ret = "\n"+json.dumps(dic)
print(ret)

其他参数:

import json
data = {'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16, 'A': 666}
json_dic2 = json.dumps(data, sort_keys=True, indent=2, separators=('|', '*'), ensure_ascii=False)
print(json_dic2)

print(json.loads(json_dic2)) # 如果改了:separators=('|','*')反序列化不行了
sort_keys = True      # 字典键的首字母的ascii码排序
ensure_ascii = False      # 显示中文
indent = 2    # key 缩进

dic = {(1, 2, 3): 'alex', 1: [1, 2, 3]}
ret = json.dumps(dic)
print(ret)  # TypeError: keys must be a string

json:
优点:跨语言,体积小
取点:只支持 int/str/list/tuple/dict
pickle:
优点:专为Python设计,支持Python所有数据类型
取点:只能在Python中使用,存储数据占空间大

shelve模块

shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的数据格式.
存入数据:

import shelve

f = shelve.open('shelve_file')
f['key'] = {'int': 10, 'float': 9.5, 'string': 'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

去除数据:

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

这里的shevle将目标作为value存在自定义的key对应的文件中

import shelve
f = shelve.open('shelve_file', flag='r')
# existing = f['key']
f['key'] = [11,22,33]
f.close()
# print(existing)

f = shelve.open('shelve_file', flag='r')
ex = f['key']
print(ex)
f.close()

f['key'] = {'int':10, 'float':9.5, 'string':'Sample data','new_value': 'this was not here before'}

configparser模块

此模块用于生成和修改常见配置文档,可以包含一个或多个节(section),每个节可以有多个参数(键=值).当前模块名称在Python3.x中改名为configparser
来看一个好多软件的常见文档格式如下:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
  
[bitbucket.org]
User = hg
  
[topsecret.server.com]
Port = 50022
ForwardX11 = no

解析文档配置:

import configparser

config = configparser.ConfigParser()

config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }

config['bitbucket.org'] = {'User':'hg'}

config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}

with open('example.ini', 'w') as configfile:

   config.write(configfile)

collections模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

namedtuple : tu = (x=1,y=2)
deque:双端队列(队列:先进先出,天猫限量抢购,栈:先进后出,计算机底层)
OrderedDict:按照键的添加值的顺序排列
defaultDict:默认给字典所有的键设置一个值,defaultDict(可调用对象)
Counter:自动计数能.n = 'aabbccccsssdddd' 'a:2,b:2,c:4,s:3,d:4

namedtuple

由于元组的不可变,namedtuple主要用于表示坐标

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x)
# 1
print(p.y)
# 2
print(p[0])
print(p[1])

类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:

#namedtuple('名称', [属性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])
deque

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

from collections import deque
q = deque(['a','b','c','d','e'])
print(q)
q.append(666)  #添加最右边
q.append(777)
q.appendleft(111)  #从最左边添加
q.appendleft(222)
q.pop()  # 从右边删除
q.popleft() # 从左边删除
q.popleft()
print(q)

deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。

OrderedDict

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
如果要保持Key的顺序,可以用OrderedDict:

dic = {}
dic['name'] = 'alex'
dic['age'] = '1000'
dic['sex'] = '男'
print(dic)
from collections import OrderedDict
# od = OrderedDict()
# od['name'] = 'alex'
# od['age'] = '1000'
# od['sex'] = '男'
# print(od)
装逼版:
d = dict([('a', 1), ('b', 2), ('c', 3)])
print(d)
from collections import OrderedDict
od1 = OrderedDict([('a', 1), ('c', 3), ('b', 2),])
print(od1)
l1 = [11,22,33,44,55,77,88,99,90]
dic = {}
for i in l1:
    if i > 66:
        if 'key1' not in dic:
            dic['key1'] = []
        dic['key1'].append(i)
    else:
        if 'key2' not in dic:
            dic['key2'] = []
        dic['key2'].append(i)
print(dic)

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序

defaultdict

有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
即: {'k1': 大于66 , 'k2': 小于66}
原生字典的解决方法:

li = [11,22,33,44,55,77,88,99,90]
result = {}
for row in li:
    if row > 66:
        if 'key1' not in result:
            result['key1'] = []
        result['key1'].append(row)
    else:
        if 'key2' not in result:
            result['key2'] = []
        result['key2'].append(row)
print(result)

defaultdict解决:

from collections import defaultdict

values = [11, 22, 33,44,55,66,77,88,99,90]

my_dict = defaultdict(list)

for value in  values:
    if value>66:
        my_dict['k1'].append(value)
    else:
        my_dict['k2'].append(value

默认给字典所有的键设置一个值,defaultDict(可调用对象),相当于把这个字典的键组成一个集合赋值到默认的键

使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:

from collections import defaultdict
dd = defaultdict(lambda: 'N/A')
dd['key1'] = 'abc'
dd['key1'] # key1存在
# 'abc'
dd['key2'] # key2不存在,返回默认值
# 'N/A'
Counter

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。

c = Counter('abcdeabcdabcaba')
print c
<!--输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})-->

random模块

random.random():大于0且小于1之间的小数,开区间
random.uniform(a,b):a到b之间的随机小数,开区间
random.randint(a,b):a到b之间的随机整数,闭区间
random.randrange(a,b,c):a到b之间的随机整数,步长为c,左闭右开区间
random.choice(list):传入一个可迭代对象,随机取一个
random.sample():随机选择多个返回,返回的个数为函数的第二个参数,不一定是可迭代对象
ramdom.shuffle():#打乱列表顺序

>>> import random
#随机小数
>>> random.random()      # 大于0且小于1之间的小数
0.7664338663654585
>>> random.uniform(1,3) #大于1小于3的小数
1.6270147180533838
#恒富:发红包

#随机整数
>>> random.randint(1,5)  # 大于等于1且小于等于5之间的整数
>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数


#随机选择一个返回
>>> random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数
>>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合
[[4, 5], '23']


#打乱列表顺序
>>> item=[1,3,5,7,9]
>>> random.shuffle(item) # 打乱次序
>>> item
[5, 1, 3, 7, 9]
>>> random.shuffle(item)
>>> item
[5, 9, 7, 1, 3]

random.choice(list)和random.sample()的区别:

import random


def function():
    lis = []
    for i in range(65, 91):
        lis.append(chr(i))
    return lis


print(random.choice(function()))


def functions():
    lis = {}
    for i in range(65, 91):
        lis[i] = chr(i)
    s = set(lis)
    print(s)
    return s


print(random.choice(functions()))  # TypeError: 'set' object does not support indexing
print(random.sample(functions(),1))

传入choice的必须是可迭代的对象

time模块

1.时间戳(timestamp)的方式:

1.time.sleep(secs)
(线程)推迟指定的时间运行。单位为秒。
2.time.time()
获取当前时间戳

print(time.time())
print(type(time.time()))
# <class 'float'>

时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量

2.格式化的时间字符串(Format String): ‘1999-12-06

%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

import time

print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(time.strftime('%Y-%m-%d %H:%M:%S'),type(time.strftime('%Y-%m-%d %H:%M:%S')))
ret = time.strftime('%Y{}%m{}%d{} %H:%M:%S').format('年','月','日')
print(ret)
print(time.strftime('%Y/%m/%d %H:%M:%S'))
print(time.strftime('%Y/%m/%d %I:%M:%S'))
print(time.strftime('%x'))
print(time.strftime('%x,%X'))
print(time.strftime('%c'))
3.元组(struct_time()):

struct_time元组公有9个元素(年,月,日,时,分,秒,一年中第几周,一年中第几天等),返回struct_time的函数主要有gmtime(),localtime(),strptime(),

索引 属性
0 tm_year(年) 比如2018
1 tm_mon(月) 1~12
2 tm_mday日) 1~31
3 tm_hour(时) 0~24
4 tm_min(分) 0~59
5 tm_sec(秒) 0~59
6 tm_wday(weekday) 0~6(0表示周日)
7 tm_yday(一年中的第几天) 1~365
8 tm_isdst(是否是夏令时) 默认-1
小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的
结构化时间:供人类看的,和1不能直接转,time.struct_time(时间戳与字符串时间中间介质.)
几种格式之间的转换

image

import time


# 格式化时间 ---->  结构化时间
ft = time.strftime('%Y/%m/%d %H:%M:%S')
st = time.strptime(ft,'%Y/%m/%d %H:%M:%S')
print(st)
# 结构化时间 ---> 时间戳
t = time.mktime(st)
print(t)

# 时间戳 ----> 结构化时间
t = time.time()
st = time.localtime(t)
print(st)
# 结构化时间 ---> 格式化时间
ft = time.strftime('%Y/%m/%d %H:%M:%S',st)
print(ft)

image

import time


# 特殊的转化
# 时间戳 ----> 特殊的格式化时间
timestamp = time.time()
ft = time.ctime(timestamp)
print(ft)
# 结构化时间 ---> 特殊的格式化时间
struct_time = time.localtime()
print(struct_time)
ft = time.asctime(struct_time)
print(ft)
struct_time =time.localtime(time.time())
print(struct_time)
ft = time.strftime('%Y-%m-%d %H:%M:%S',struct_time)
print(ft)

ft1 = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(2900000000))
print(ft1)

计算时间差
import time
true_time=time.mktime(time.strptime('2017-09-11 08:30:00','%Y-%m-%d %H:%M:%S'))
time_now=time.mktime(time.strptime('2017-09-12 11:00:00','%Y-%m-%d %H:%M:%S'))
dif_time=time_now-true_time
struct_time=time.gmtime(dif_time)
print('过去了%d年%d月%d天%d小时%d分钟%d秒'%(struct_time.tm_year-1970,struct_time.tm_mon-1,
                                       struct_time.tm_mday-1,struct_time.tm_hour,
                                       struct_time.tm_min,struct_time.tm_sec))

os模块

os模块是与操作系统交互的一个接口

#当前执行这个python文件的工作目录相关的工作路径
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')

#和文件夹相关
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

# 和文件相关
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息

# 和操作系统差异相关
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

# 和执行系统命令相关
os.system("bash command")  运行shell命令,直接显示
os.popen("bash command).read()  运行shell命令,获取执行结果
os.environ  获取系统环境变量

#path系列,和路径相关
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.path.getsize(path) 返回path的大小

sys模块

sys模块是与python解释器交互的一个接口

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

sys.argv这个主要用在类似于数据库的登录,后边要跟参数

posted @ 2018-07-10 11:58  咕咚!  阅读(842)  评论(0编辑  收藏  举报