一个文件(以“.py”为后缀名的文件)就叫做一个模块,每一个模块在python里都被看做是一个独立的文件。模块可以被项目中的其他模块、一些脚本甚至是交互式的解析器所使用,它可以被其他程序引用,从而使用该模块里的函数等功能,使用Python中的标准库也是采用这种方法。
注意:自定义模块时不要和系统内置的模块名相同
为了便于管理模块,会用包容纳多个模块。包就是目录,但该目录下必须存在 init.py 文件。
常见结构如下:
package_root
|——__init__.py
|——module1.py
|——module2.py
|_____package_sub
|——__init__.py
|——sub_module1.py
|——sub_module2.py
|_____sub_module3.py
......
注意事项:
几个符号要记牢:
例:在sub_module1中需要导入module2
寻找module2的路径为:package_root.module2
绝对导入更清晰,如果包不是特别复杂,不是特别易变,那么还是建议采用绝对导入
import [模块 as 短名称,模块 as 短名称...]
import会导入模块中的所有内容(引入多个用逗号分隔)
例:
import random as rd,time
若层级过多,使用.进行下级寻找
例:
import os.path
缺点:
1.无法进行相对导入
2.无法细致到只导入模块的某一部分
3.导入后若没有别名仍然需要带上导入的前缀
__all__ =[ "子级元素1","子级元素2"...... ]
子级元素可以是子包、子模块、子变量、子函数、模块中的类等等
from...import支持包内相对导入
from...import导入后,使用时from后前缀可省略
例:
package_root
|——__init__.py
|——module1.py
|——module2.py
|——def func1()
|——class C1
|——init_data = 1.0
|_____package_sub
|——__init__.py
|——sub_module.py
sub_module中需要module2全体:
from ..module2 import *
C1()
print(init_data)
func1()
sub_module中只需要module2的类C1:
from ..module2 import C1
C1()
print(init_data) # err
func1() # err
1.所有执行的开始模块,无论模块是否在包内,模块名被自动限定为"main",称顶级模块;
2.有相对导入的模块不要直接运行;
3.模块被导入后会立即执行其中的语句,so本模块的测试语句最好放入:
if __name__ == '__main__':
"""
测试本模块的语句
放在这个位置 导入时不会执行
"""
pass
Python有一套很有用的标准库(standard library)。标准库会随着Python解释器,一起安装在你的电脑中的。
它是Python的一个组成部分。这些标准库是Python为你准备好的利器,可以让编程事半功倍。
str:字符串;
字符串是不可变类型,字符串是程序中非常常见的类型。
字符串声明:双引号或者单引号中的数据,就是字符串。
例如:
user_name='mayun'
pwd="*********"
编码格式
string.find(str, beg=0, end=len(string))
#检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
string.rfind(str, beg=0, end=len(string))
#类似于 find()函数,不过是从右边开始查找.
string.index(str, beg=0, end=len(string))
#类似于 find()函数,但是找不到报异常.
string.rindex(str, beg=0, end=len(string))
#类似于 rfind()函数,但是找不到报异常.
string.count(str, beg=0, end=len(string))
#检测 str 是否包含在 string 中出现的次数,如果 beg 和 end 指定范围,则检查是否包含在指定范围内
string.split(str="", num=string.count(str))
#以 str 为分隔符切片 string,如果 num有指定值,则仅分隔 num 个子字符串
string.splitlines([keepends])
#按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
string.partition(str)
#有点像 find()和 split()的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string.
string.rpartition(str)
# 类似于 partition()函数,不过是从右边开始.
string.startswith(obj, beg=0,end=len(string))
#检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
string.endswith(obj, beg=0,end=len(string))
#检查字符串是否是以 obj 结尾,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
string.isalnum() #所有字符都是字母或数字则返回 True,否则返回 False
string.isalpha() #所有字符都是字母则返回 True,否则返回 False
string.isdigit() #所有字符都是数字则返回 True,否则返回 False
string.isupper() #所有字符都是大写则返回 True,否则返回 False
string.islower() #所有字符都是小写则返回 True,否则返回 False
string.isspace() #只包含空格则返回 True,否则返回 False
string.capitalize()
# 把字符串的第一个字符大写
string.upper()
# 转换 string 中的小写字母为大写
string.lower()
# 转换 string 中的大写字母为小写
string.ljust(width)
# 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
string.rjust(width)
# 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
string.center(width)
# 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串
string.strip([obj])
# 删除 string 字符串前后的的obj,如果不传参数,删除前后空格
string.lstrip([obj])
# 删除 string 字符串左面的obj,如果不传参数,删除左面空格
string.rstrip([obj])
# 删除 string 字符串右面的obj,如果不传参数,删除右面空格
string.join(seq)
# 以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
# 日期模块的引入:
from datetime import datetime
# 获取当前日期对象:年月日时分秒.毫微秒
datetime.now()
# 自己设定年月日时分秒获取日期时间对象
datetime(year, month, day [,hour, minute, second])
# 根据时间戳获取日期时间
print(datetime.fromtimestamp(999989990))
日期时间格式化成字符串
datetime.strftime(“%Y-%m-%d %H:%M:%S”)
from datetime import datetime
dt=datetime.now()
t=dt.strftime("%Y{y}%m{m}%d{d} %H:%M:%S").format(y="年",m="月",d="日")
print(t)
字符串转换日期,经常用于检测日期字符串的合法性,若日期不正常会出转换异常
dt = datetime.strptime("2017-10-01 00:00:00", "%Y-%m-%d %H:%M:%S")
# 计算日期相差天数
dt = datetime.strptime("2019-7-21 00:00:00", "%Y-%m-%d %H:%M:%S")
print((dt - datetime.now()).days)
# 计算n(天\小时\分钟\秒等)后的日期
import datetime as d_t
print(datetime.now() + d_t.timedelta(days=50, seconds=-10000))
此模块的函数都是日历相关的,例如打印某月的字符月历。
模块包含了以下内置函数:
calendar.calendar(year[, w=2, l=1, c=6,m=3])
# 某年的所有月历 默认3个月一行,c为月历间隔距离, w是日期间隔距离,l是每星期行数,一般默认即可
print(calendar.calendar(2019))
# 最方便的写法:
calendar.prcal(year[, w=2, l=1, c=6,m=3]) # 自动输出
calendar.month(year,month[,w=2,l=1])
# 某月的所有周历 w是日期间隔距离,l是每星期行数,一般默认即可
print(calendar.month(2019, 7))
# 最方便写法:
calendar.prmonth(year,month[,w=2,l=1]) # 自动输出
# 获取某月的周历嵌套列表:不在当月的日期记为0
calendar.monthcalendar(year,month)
# 判断闰年:
calendar.isleap(year)
# 判断间隔的年份[y1,y2)中的闰年数:
calendar.leapdays(y1,y2)
# 获取月份首天的星期数及总天数
calendar.monthrange(year,month)
返回两个整数。第一个是该月的第一天是星期几(0-6对应周一-周日),第二个是该月的天数
# 获取某日是星期几
calendar.weekday(year,month,day)
# 根据日历上的某天获取时间戳 以便向其他日期时间转换:
calendar.timegm(tupletime)
和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。
模块模块的引入:import time
time.sleep(secs)
线程休眠固定秒数后醒来继续执行
time.time()
返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
示例:
计算下面的程序花费了多少时间
for i in range(1000000):
print(i)
方法:在代码段前后加上time.time() 计算时间差即可得到运行所需时间
start = time.time()
for i in range(1000000):
print(i)
end = time.time()
print(str.format("程序花费了{}毫秒", int((end - start)*1000)))
python中math模块中提供的基本数学函数:
sin(x) :求x的正弦
cos(x) :求x的余弦
asin(x):求x的反正弦
acos(x):求x的反余弦
tan(x) :求x的正切
atan(x):求x的反正切
fmod(x,y):求x/y的余数
ceil(x) :取不小于x的最小整数
floor(x):求不大于x的最大整数
fabs(x):求绝对值
pow(x,y) :求x的y次幂
log10(x) :求x的以10位底的对数
sqrt(x) :求x的平方根
factorial(x) 求x的阶乘
trunc(x) 求x的整数部分
sys模块提供了一系列有关Python运行环境的变量和函数
sys模块常用的功能:
sys.argv
# 获取当前正在执行的命令行参数的参数列表(list)
sys.platform
# 获取当前执行环境的平台,如win32表示是Windows 32bit操作系统,linux2 表示是linusys.path 在python启动时,sys.path 根据内建规则、PYTHONPATH变量进行初始化。
sys.builtin_module_names
返回一个列表,包含内建模块的名字
sys.exit(n)
调用sys.exit(n) 可以中途退出程序,当参数非0时,会引发一个SystemExit 异常,从而可以在主程序中捕获该异常。
文件是一些具有永久存储及特定顺序的字节组成的一个有序的、具有名称的集合。
在各种介质上(可移动磁盘、硬盘、CD、网络 等)存储的集合数据。
通常情况下文件按照树状目录进行组织,每个文件都有文件名、文件所在路径、创建时间、访问权限等属性。
I/O:Input/Output
输入和输出都是有参照物的 参照物就是运存即程序
Input就是从其他介质向运存输入,称为“读”(read)介质
Output就是从运存输出到其他介质,称为“写”(write)介质
流:
输入和输出是需要“管道”传输的,这个“管道”中流传的是数据,形象化比喻为数据“流”,和我们常识中的水流是相似的
异质性问题带了的后续影响:同步和异步;
运存的处理速度很快而其他介质处理速度相对较慢;
若运存持续等待其他介质完成后才能去做其他事情,就叫同步,但是时间就被白白浪费;若运存不等待,只将数据存入流中,完毕后转做其他事情,其他介质慢慢接收流的数据,称为异步处理,这大大节省了cpu时间,但是异步加重了编程的复杂度。
由于文件在操作系统的资源管理器上,so我们必须借助和操作系统相关的模块:
os(operating system)
import os
print(os.name)
# 如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统
print(os.environ)
print(os.environ.get("path"))
os.access("new_dir", os.F_OK) # 查看目录是否存在
os.F_OK : 是否存在
os.R_OK : 是否可读
os.W_OK : 是否可写
os.X_OK : 是否可执行
print(os.getcwd())
os.chdir("..")
print(os.getcwd())
if not os.access("new_dir", os.F_OK):
os.mkdir("new_dir")
os.makedirs("mydir/sub1/sub2/sub3", exist_ok=True)
os.rmdir("new_dir")
os.removedirs("mydir/sub1/sub2/sub3")
os.open("1.txt", os.O_CREAT)
为了防止资源泄露:创建后关闭对文件的连接
os.close(os.open("1.txt", os.O_CREAT))
os.remove("1.txt")
os.rename("1.txt", "2.txt")
# 可以自动递归创建新目录
os.renames("1.txt", "aaa/2.txt")
print(os.listdir("."))
for root, subs, files in os.walk(".", True):
print("当前目录", root)
print("子目录:")
for i in subs:
print(root + "\\" + i)
print("子文件:")
for i in files:
print(root + "\\" + i)
os.path有四大职责:
1.格式化文件或目录路径
2.文件属性获取
3.辨识路径(存在or不存在、绝对or相对、目录or文件等)
4.解读路径
import os.path
import time
# 获取绝对路径
print(os.path.abspath("."))
# 返回一个路径的当前目录或文件名
print(os.path.basename(r"aaa\2.txt"))
# 返回一个路径的父目录
print(os.path.dirname(r"aaa\2.txt"))
# os.path.join(path1[, path2[, ...]]) 把目录和文件名合成一个路径
print(os.path.join("c:/", "aaa", "1.txt"))
# 规范path字符串形式
print(os.path.normpath(r"./aaa\bbb/ccc\1.txt"))
# 得到得到文件的大小
print(os.path.getsize("1.txt"))
# 返回最近访问时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getatime("."))))
# 返回最近文件修改时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime("."))))
# 返回文件 path 创建时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime("."))))
# 判断路径是否存在
print(os.path.exists(r".\5.py"))
# 判断是否为绝对路径
print(os.path.isabs("."))
# 判断路径是否为文件
print(os.path.isfile("."))
# 判断路径是否为目录
print(os.path.isdir("."))
# 路径拆分为两部分,后一部分总是最后级别的目录或文件名
print(os.path.split(r"aaa\bbb\2.txt"))
# 路径拆分为两部分,后一部分总是文件的后缀名
print(os.path.splitext(r"aaa\bbb\2.mp4"))
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件 open(文件名,访问模式)
示例如下:
f = open('Python.txt', 'w')
close( )
或者:
# 新建一个文件,文件名为:test.txt
f = open('test.txt', 'w')
# 关闭这个文件
f.close()
# with open语句省略关闭
with open('test.txt', 'w') as f:
f.read()
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
f = open('python.txt', 'r')
content = f.read(5)
print(content)
print("-"*30)
content = f.read()
print(content)
f.close()
注意:如果open是只读打开一个文件,那么可以不用写打开的模式,
即只写 open('python.txt')
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
f = open('python.txt', 'r')
content = f.readlines()
print(type(content))
i=1
for temp in content:
print(i, temp)
i+=1
f.close()
f = open('python.txt', 'r')
content = f.readline()
print("1:", content)
content = f.readline()
print("2:", content)
f.close()
写数据(write)
使用write()/writelines
可以完成向文件写入数据
f = open('Test.txt', 'w')
f.write('hello world, i am here!')
f.close()
注意:如果文件不存在那么创建,如果存在那么就先清空,然后写入数据
import os
#原始路径,目标路径
def Copy_Files(oriPath,endPath):
#判断路径是否存在
endPathDir=os.path.dirname(endPath)
if not os.path.exists(endPathDir):
os.makedirs(endPathDir)
#读取数据并写入数据
with open(oriPath,"rb") as fr:
r=fr.read()
with open(endPath,"wb") as fw:
fw.write(r)
通过将对象序列化可以将其存储在变量或者文件中,可以保存当时对象的状态,实现其生命周期的延长。并且需要时可以再次将这个对象读取出来。
import pickle
#字典序列化
dic = {'age': 23, 'job': 'student'}
byte_data = pickle.dumps(dic)
# out -> b'\x80\x03}q\x00(X\x03\x00\x00\...'
print(byte_data)
#字典反序列化
obj = pickle.loads(byte_data)
print(obj)
# 序列化
with open('abc.txt', 'wb') as f:
dic = {'age': 23, 'job': 'student'}
pickle.dump(dic, f)
# 反序列化
with open('abc.txt', 'rb') as f:
aa = pickle.load(f)
print(aa)
print(type(aa)) #
pickle可以很方便地序列化所有对象。不过json作为更为标准的格式,具有更好的可读性(pickle是二进制数据)和跨平台性。是个不错的选择。
json使用的四个函数名和pickle一致。
import json
dic = {'age': 23, 'job': 'student'}
dic_str = json.dumps(dic)
print(type(dic_str), dic_str)
# out: {"age": 23, "job": "student"}
dic_obj = json.loads(dic_str)
print(type(dic_obj), dic_obj)
# out: {'age': 23, 'job': 'student'}
import json
dic = {'age': 23, 'job': 'student'}
with open('abc.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
with open('abc.json', encoding='utf-8') as f:
obj = json.load(f)
print(obj)
异常实际上是程序中错误导致中断了正常的指令流的一种事件.
优点:
1.把错误代码从常规代码中分离出来
2.把错误传播给调用堆栈
3. 按错误类型和错误差别分类
4. 系统提供了对于一些无法预测的错误的捕获和处理
什么情况下使用异常机制?
1.当方法因为自身无法控制的原因而不能完成其任务
文件不存在,网络连接无法建立……
2.处理在引入模块中抛出的异常:
3.在大的项目中采用统一的方式处理异常时:
如编写一个文字处理器
4.异常应该是不经常发生但却可能发生的故障:
一定发生的事件不应该用异常机制来处理
5.异常处理用于使系统从故障中恢复:
提示信息/不产生无效的结果/释放资源
注意事项:
1.不同的异常处理策略
2.终止程序会导致资源泄漏,利用异常处理释放资源
3.尽可能近地处理异常,这样程序清晰易读
4.能在局部处理的错误不要使用异常机制,异常机制的处理比正常处理效率低
try:
# 接受监视的程序块,在此区域内发生的异常,由except中指定的程序处理
# 不能有其它语句分隔
except 要处理的异常种类1 as 标识符1:
# 处理异常
except 要处理的异常种类2 as 标识符2:
# 处理异常
......
或者
except (异常种类1, 异常种类2...) as 标识符...:
# 处理异常
或者
except:
# 上面未捕获的处理异常
else:
# 未监视到异常时执行的代码
finally:
# 有无异常均会执行的代码
- BaseException # 所有异常的父类
- SystemExit # 由sys.exit()抛出的异常
- KeyBoardInterrupt # 通常由ctrl+c或者Delete抛出的异常
- GeneratorExit # 生成器(generator)发生异常来通知退出
- Exception # 常规异常基类
- StopIteration # 迭代器没有更多的值
- StopAsyncIteration # 由异步迭代的__anext__()抛出的异常
- ArithmeticError # 各种算数错误引起的异常
- FloatingPointError # 浮点数操作错误
- OverflowError # 结果超出范围
- ZeroDivisionError # 0为除数异常
- AssertionError # assert错误异常
- AttributeError # 属性引用异常
- BufferError # 缓存错误
- EOFError # 读不到数据
- ImportError # import错误
- ModuleNotFoundError # 找不到模块
- LookupError # 由索引和key值引起的异常
- IndexError # 索引错误
- KeyError # 字典key值错误
- MemortError # 内存溢出异常
- NameError # 本地和全局找不到变量名
- UnboundLocalError # 局部变量没有赋值
- OSError # system错误
- BlockingIOError # 调用阻塞异常错误
- ChildProcessError # 子进程
- ConnectionError # 连接
- BrokenPipeError # 管道读写异常
- ConnectionAbortedError # 连接失败
- ConnectionRefusedError # 连接拒绝
- ConnectionResetError # 连接重置
- FileExistsError # 创建文件和文件夹错误
- FileNotFoundError # 文件未找到
- InterruptedError # 中断错误
- IsADirectoryError # 文件操作用在文件夹上
- NotADirectoryError # 不是文件夹
- PermissionError # 权限
- ProcessLookupError # 进程不存在
- TimeoutError # 超时
- ReferenceError # 试图访问已经垃圾回收的对象异常
- RuntimeError #
- NotImplementedError # 未实现抽象方法异常
- RecursionError # 超出最大递归深度
- SyntaxError # 语法错误
- IndentationError # 缩进错误
- TabError # Tab 和空格混用
- SystemError # 解释器中断
- TypeError # 对类型无效的操作
- ValueError # 赋值错误
- UnicodeError # Unicode 相关的错误
- UnicodeEncodeError # unicode编码错误
- UnicodeDecodeError # unicode解码错误
- UnicodeTranslateError # unicode转换错误
- Warning # 警告的基类
- DeprecationWarning # 关于被弃用的特征的警告
- PendingDeprecationWarning # 表明此操作将来会被弃用
- UserWarning # 用户代码生成的警告
- SyntaxWarning # 可疑的语法的警告
- RuntimeWarning # 可疑的运行时行为警告
- FutureWarning # 关于构造将来语义会有改变的警告
- ImportWarning # 导入警告
- UnicodeWarning # unicode相关警告
- BytesWarning # 字节相关警告
- ResourceWarning # 资源使用情况警告
手动抛出异常的方法:raise 空|异常对象;
注意:单raise时,会将当前捕获的异常直接再次抛出;
raise exception_obj;
抛出异常: 不是出错产生,而是人为地抛出;
1.任何从BaseException派生的类都可以用raise语句抛出,抛出异常用来表明程序遇到的错误无法正常执行而需要异常处理;
raise BaseException(“some infomation”);
2.异常抛出点后的代码在抛出异常后不再执行,也可以说异常的抛出终止了代码段的执行。
异常是一个类,用户定义的异常一般继承自Exception:
'''自定义的异常类'''
class ShortInputException( Exception ):
def __init__( self , length, atleast):
super().__init__()
self .length = length
self .atleast = atleast
def main()
try:
s = input( '请输入 --> ' )
if len(s) < 3 :
#raise引发一个你定义的异常
raise ShortInputException(len(s), 3 )
#x这个变量被绑定到了错误的实例
except ShortInputException as result:
print(result)
print( 'ShortInputException: 输入的长度是 %d,长度至少应是 %d' % (result.length,
result.atleast))
else:
print( '没有异常发生.' )
main()