assert的语法格式:assert expression,它的等价语句为:
if not expression:
raise AssertionError
这段代码用来检测数据类型的断言,因为 a_str
是 str
类型,所以认为它是 int
类型肯定会引发错误。
>>> a_str = 'this is a string'
>>> type(a_str)
<type 'str'>
>>> assert type(a_str)== str
>>> assert type(a_str)== int
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
assert type(a_str)== int
AssertionError
——from:[Python]断言assert的用法
我们先看:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
fab(5)
执行以上代码,我们可以得到如下输出:
1
1
2
3
5
结果没有问题,但有经验的开发者会指出,直接在 fab 函数中用 print 打印数字会导致该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列。
要提高 fab 函数的可复用性,最好不要直接打印出数列,而是返回一个 List。以下是 fab 函数改写后的第二个版本:
def fab(max):
n, a, b = 0, 0, 1
L = []
while n < max:
L.append(b)
a, b = b, a + b
n = n + 1
return L
for n in fab(5):
print n
可以使用如下方式打印出 fab 函数返回的 List:
1
1
2
3
5
改写后的 fab 函数通过返回 List 能满足复用性的要求,但是更有经验的开发者会指出,该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,最好不要用 List
…
使用 yield 的第四版:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 使用 yield
# print b
a, b = b, a + b
n = n + 1
for n in fab(5):
print n
第四个版本的 fab 和第一版相比,仅仅把 print b 改为了 yield b,就在保持简洁性的同时获得了 iterable 的效果。
调用第四版的 fab 和第二版的 fab 完全一致:
1
1
2
3
5
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法),这样我们就可以更清楚地看到 fab 的执行流程:
执行流程:
>>>f = fab(5)
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。
我们可以得出以下结论:
一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。
——from:Python yield 使用浅析 | 菜鸟教程
以下实例演示了 os.path 相关方法的使用:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
print( os.path.basename('/root/runoob.txt') ) # 返回文件名
print( os.path.dirname('/root/runoob.txt') ) # 返回目录路径
print( os.path.split('/root/runoob.txt') ) # 分割文件名与路径
print( os.path.join('root','test','runoob.txt') ) # 将目录和文件名合成一个路径
补充一个:
os.path.splitext(“文件路径”)
分离文件名与扩展名;默认返回 (fname,fextension) 元组,可做分片操作。例子:import os path_01='D:/User/wgy/workplace/data/notMNIST_large.tar.gar' path_02='D:/User/wgy/workplace/data/notMNIST_large' root_01=os.path.splitext(path_01) root_02=os.path.splitext(path_02) print(root_01) print(root_02)结果:
('D:/User/wgy/workplace/data/notMNIST_large.tar', '.gar') ('D:/User/wgy/workplace/data/notMNIST_large', '')
执行以上程序输出结果为:
runoob.txt
/root
('/root', 'runoob.txt')
root/test/runoob.txt
以下实例输出文件的相关信息。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import time
file='/root/runoob.txt' # 文件路径
print( os.path.getatime(file) ) # 输出最近访问时间
print( os.path.getctime(file) ) # 输出文件创建时间
print( os.path.getmtime(file) ) # 输出最近修改时间
print( time.gmtime(os.path.getmtime(file)) ) # 以struct_time形式输出最近修改时间
print( os.path.getsize(file) ) # 输出文件大小(字节为单位)
print( os.path.abspath(file) ) # 输出绝对路径
print( os.path.normpath(file) ) # 规范path字符串形式
执行以上程序输出结果为:
1539052805.5735736
1539052805.5775735
1539052805.5735736
time.struct_time(tm_year=2018, tm_mon=10, tm_mday=9, tm_hour=2, tm_min=40, tm_sec=5, tm_wday=1, tm_yday=282, tm_isdst=0)
7
/root/runoob.txt
/root/runoob.txt
——from:Python os.path() 模块 | 菜鸟教程
1、在 Python2.x 中 raw_input( ) 和 input( ),两个函数都存在,其中区别为:
- raw_input( ) 将所有输入作为字符串看待,返回字符串类型。
- input( ) 只能接收"数字"的输入,在对待纯数字输入时具有自己的特性,它返回所输入的数字的类型( int, float )。
2、在 Python3.x 中 raw_input( ) 和 input( ) 进行了整合,去除了 raw_input( ),仅保留了 input( ) 函数,其接收任意任性输入,将所有输入默认为字符串处理,并返回字符串类型。
——from:Python2.x 和 Python3.x 中 raw_input( ) 和 input( ) 区别 | 菜鸟教程
(1)其他 --> int
str -> int:(如果字符串中有数字(0-9)和正负号(+/-)以外的字符,就会报错。)
int('1209') # 1209
int('-12') # -12
int('+1008') # 1008
(2)其他 --> flot
str -> float:(如果字符串含有正负号(+/-)、数字(0-9)和小数点(.)以外的字符,则不支持转换。)
float('-1209') # -1209.0
float('-0120.29023') # -120.29023
(3)其他 --> str
str()
函数可以将任意对象转换为字符串。
int -> str:(int 转换 str 会直接完全转换)
str(12) # 12
float -> str:(float 转换 str 会去除末位为 0 的小数部分。)
str(-12.90) # -12.9
更多参考:史上最全的 Python 3 类型转换指南 - 格物
glob 是 python 自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,类似于 Windows 下的文件搜索,支持通配符操作。
查找文件只用到三个匹配符:*
、?
、[]
。*
匹配 0 个或多个字符;?
匹配单个字符;[]
匹配指定范围内的字符,如:[0-9]匹配数字。
1、glob方法
glob 模块的主要方法就是 glob,该方法返回所有匹配的文件路径列表(list);它只有一个参数 pathname,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径。其返回的文件名只包括当前目录里的文件名,不包括子文件夹里的文件。
示例:
import glob
#获取指定目录下的所有图片
print glob.glob(r"E:\Picture\*\*.jpg")
#获取上级目录的所有.py文件
print glob.glob(r'../*.py') #相对路径
2、iglob方法
获取一个迭代器( iterator )对象,使用它可以逐个获取匹配的文件路径名。与glob.glob() 的区别是:glob.glob同时获取所有的匹配路径,而 glob.iglob 一次只获取一个匹配路径。
直接看代码(注:上级目录有两个 py 文件 a.py
、b.py
)。
使用 iglob 方法:
import glob
#父目录中的.py文件
f = glob.iglob(r'../*.py')
print(f)
for py in f:
print(py)
打印结果:
<generator object _iglob at 0x000000000296EC50>
..\a.py
..\b.py
使用 glob 方法:
import glob
#父目录中的.py文件
f = glob.glob(r'../*.py')
print(f)
for py in f:
print(py)
打印结果:
['..\\a.py', '..\\b.py']
..\a.py
..\b.py
1、保存列表为.txt文件
#1/list写入txt
ipTable = ['158.59.194.213', '18.9.14.13', '58.59.14.21']
fileObject = open('sampleList.txt', 'w')
for ip in ipTable:
fileObject.write(ip)
fileObject.write('\n')
fileObject.close()
2、字典保存
#2/dict写入json
import json
dictObj = {
'andy':{
'age': 23,
'city': 'shanghai',
'skill': 'python'
},
'william': {
'age': 33,
'city': 'hangzhou',
'skill': 'js'
}
}
jsObj = json.dumps(dictObj)
fileObject = open('jsonFile.json', 'w')
fileObject.write(jsObj)
fileObject.close()
方法1:
import datetime
starttime = datetime.datetime.now()
#long running
#do something other
endtime = datetime.datetime.now()
print (endtime - starttime).seconds
datetime.datetime.now() 获取的是当前日期,在程序执行结束之后,这个方式获得的时间值为程序执行的时间。
方法2:
start = time.time()
#long running
#do something other
end = time.time()
print end-start
time.time()获取自纪元以来的当前时间(以秒为单位)。如果系统时钟提供它们,则可能存在秒的分数。所以这个地方返回的是一个浮点型类型。这里获取的也是程序的执行时间。
方法3:
start = time.clock()
#long running
#do something other
end = time.clock()
print end-start
time.clock() 返回程序开始或第一次被调用 clock() 以来的 CPU 时间。 这具有与系统记录一样多的精度。返回的也是一个浮点类型。这里获得的是CPU的执行时间。
注:程序执行时间 = cpu时间 + io时间 + 休眠或者等待时间。
方法比较:
- 通过对以上方法的比较我们发现,方法二的精度比较高。方法一基本上是性能最差的。这个其实是和系统有关系的。一般我们推荐使用方法二和方法三。我的系统是Ubuntu,也就是Linux系统,方法二返回的是UTC时间。 在很多系统中time.time()的精度都是非常低的,包括windows。
- python 的标准库手册推荐在任何情况下尽量使用time.clock().但是这个函数在windows下返回的是真实时间(wall time)
- 方法一和方法二都包含了其他程序使用CPU的时间。方法三只计算了程序运行CPU的时间。
- 方法二和方法三都返回的是浮点数
参考:
Python中有两个模块可以完成时间操作:time
和datetime
相比较而言 datetime 更强大。
如果要获取微秒级别的时间差,可以利用以下代码:
import datetime
begin = datetime.datetime.now()
end = datetime.datetime.now()
k = end - begin
print (end-begin).days # 0 天数
print (end-begin).total_seconds() # 30.029522 精确秒数
print (end-begin).seconds # 30 秒数
print (end-begin).microseconds # 29522 毫秒数
亲自实践某段代码:
starttime = datetime.datetime.now()
print(starttime)
#long running
#do something other
endtime = datetime.datetime.now()
print(endtime)
print((endtime - starttime).seconds)
结果:
2019-06-18 00:20:31.576806
2019-06-18 00:20:41.231358
9
使用:print((endtime - starttime).total_seconds)
2019-06-18 00:21:47.085125
2019-06-18 00:21:56.225648
9.140523
关于 time 库中表示时间的方法,官方给出了 2 种:
1.从1970-01-01 00:00:00 UTC,开始到现在所经历的时间,以浮点数的'秒'来表示
>>>time.time()
1517362540.347517
2.用结构化的时间组(year,month,day,hours,minutes,seconds....)来表示从1970-01-01 00:00:00 UTC,开始到现在所经历的时间.
>>>time.gmtime()
time.struct_time(tm_year=2018, tm_mon=1, tm_mday=31, tm_hour=1, tm_min=37,
tm_sec=36, tm_wday=2, tm_yday=31, tm_isdst=0)
time包中的功能都很实用:
-
**time.clock()**返回程序运行的整个时间段中中CPU运行的时间,下面会重点介绍
-
**time.sleep()**爬虫中常用,让程序暂停执行指定的秒数,如time.sleep(2)
-
**time.localtime()**用结构化的时间组,表示本地时间
来用 time 计算运行时间。定义一个函数run():
def run():
start = time.time()
for i in range(1000):
j = i * 2
for k in range(j):
t = k
print(t)
end = time.time()
print('程序执行时间: ',end - start)
可以看到,程序执行时间是5.73039174079895s。
现在,让我们用 time.clock() 来看看程序执行过程中 CPU 执行了多长时间:
def run2():
start = time.clock()
for i in range(1000):
j = i * 2
for k in range(j):
t = k
print(t)
end = time.clock()
print('CPU执行时间: ',end - start)
可见,此段代码 CPU 执行时间为:5.3150249999999915。
那么问题来了,CPU 真的执行了这么长时间么?会不会有什么东西是我没考虑进去的呢?
仔细看一下,这段程序主要内容就是两个for循环,for循环执行计算的时候 CPU 肯定是在运行的,那么 print() 函数打印期间这个时间段的 CPU 执行时间有没有算进去?
带着疑问,我们进行第三次测试,此次我们去掉 print(),直接让 CPU 完成整个 for 循环的计算:
def run3():
start = time.clock()
for i in range(1000):
j = i * 2
for k in range(j):
t = k
end = time.clock()
print('CPU执行时间: ',end - start)
结果:
>>> run3()
CPU执行时间: 0.04683999999997468
可以看见,CPU的执行时间瞬间降低到0.04s,细想一下,其实不难理解。
因为去掉了print(),所以整个run3()函数就只剩下完整的for循环,CPU可以连续执行,(不必一遍for循环一边print()来回切换),连续执行的CPU还是很快的~
所以,这给了我一个启发,以后写代码时,要精简不必要的开销,譬如经常使用print()。。。
——from:Python计算程序运行时间—time.time()、time.clock() - 知乎
1、使用成员操作符 in
>>> s='nihao,shijie'
>>> t='nihao'
>>> result = t in s
>>> print result
True
2、使用 string 模块的 find()/rfind() 方法
>>> import string
>>> s='nihao,shijie'
>>> t='nihao'
>>> result = string.find(s,t)!=-1
>>> print result
True
>>> result = string.rfind(s,t)!=-1
>>> print result
True
详细参考:Python find()方法 | 菜鸟教程 | Python rfind()方法 | 菜鸟教程
3、使用 string 模块的 index()/rindex() 方法
index()/rindex() 方法跟 find()/rfind() 方法一样,只不过找不到子字符串的时候会报一个 ValueError 异常。
import string
def find_string(s,t):
try:
string.index(s,t)
return True
except(ValueError):
return False
s='nihao,shijie'
t='nihao'
result = find_string(s,t)
print result #True
详细参考:Python index()方法 | 菜鸟教程 | Python rindex()方法 | 菜鸟教程
4、使用字符串对象的 find()/rfind()、index()/rindex() 和 count() 方法
>>> s='nihao,shijie'
>>> t='nihao'
>>> result = s.find(t)>=0
>>> print result
True
>>> result=s.count(t)>0
>>> print result
True
>>> result=s.index(t)>=0
>>> print result
True
——from:Python判断一个字符串是否包含子串的几种方法
遍历文件夹中的所有子文件夹及子文件使用 os.walk() 方法非常简单。
语法格式大致如下:
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
- top -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files),
【文件夹路径, 文件夹名字, 文件名】
。- root 所指的是当前正在遍历的这个文件夹的本身的地址
- dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
- files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
- topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历 top文件夹,与 top 文件夹中每一个子目录。
- onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
- followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。
示例如下:
1、显示目录下所有文件
#conding=utf8
import os
g = os.walk(r"e:\test")
for path,dir_list,file_list in g:
for file_name in file_list:
print(os.path.join(path, file_name) )
2、显示所有子目录
#conding=utf8
import os
g = os.walk("e:\test")
for path,dir_list,file_list in g:
for dir_name in dir_list:
print(os.path.join(path, dir_name) )
参考:Python遍历文件夹下所有文件及目录 | Python os.walk() 方法 | 菜鸟教程
创建一个包含子文件夹和文件的 walk 文件夹,通过终端 tree 看一下目录结构:
walk
├── test1
│ ├── test1_1
│ │ ├── test1_1_1
│ │ └── test1_1_a.py
│ ├── test1_2
│ │ └── test1_2_1
│ ├── test1_3
│ ├── test1_a.py
│ └── test1_b.py
├── test2
│ ├── test2_1
│ └── test2_a.py
├── test3
└── test.py
我们通过 for 循环遍历 os.walk() 的返回结果:
import os
for root, dirs, files in os.walk("/home/python/walk",True):
print("root:%s"%root)
print("dirs:%s"%dirs)
print("files:%s"%files)
print("-------------------------------")
运行结果如下:
root:/home/python/walk
dirs:['test2', 'test1', 'test3']
files:['test.py']
-------------------------------
root:/home/python/walk/test2
dirs:['test2_1']
files:['test2_a.py']
-------------------------------
root:/home/python/walk/test2/test2_1
dirs:[]
files:[]
-------------------------------
root:/home/python/walk/test1
dirs:['test1_2', 'test1_3', 'test1_1']
files:['test1_a.py', 'test1_b.py']
-------------------------------
root:/home/python/walk/test1/test1_2
dirs:['test1_2_1']
files:[]
-------------------------------
root:/home/python/walk/test1/test1_2/test1_2_1
dirs:[]
files:[]
-------------------------------
root:/home/python/walk/test1/test1_3
dirs:[]
files:[]
-------------------------------
root:/home/python/walk/test1/test1_1
dirs:['test1_1_1']
files:['test1_1_a.py']
-------------------------------
root:/home/python/walk/test1/test1_1/test1_1_1
dirs:[]
files:[]
-------------------------------
root:/home/python/walk/test3
dirs:[]
files:[]
-------------------------------
注意:如果你传入的需要遍历的路径是一个相对路径的话,那么返回的 dirpath 即 root 也将是相对路径。
使用 os.walk() 获取文件夹下的文件大小:
import os
from os.path import join,getsize
def getdirsize(dir):
size = 0
for root,dirs,files in os.walk(dir):
size += sum([getsize(join(root,name)) for name in files])
return size
——from:os.walk的使用及获取文件夹下所有文件的大小 - 简书
##读取文件夹下的所有文件 os.listdir
os.listdir()
方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序。 它不包括 '.' 和 '..' 即使它在文件夹中。只支持在 Unix, Windows 下使用。
示例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, sys
# 打开文件
path = "/var/www/html/"
dirs = os.listdir( path )
# 输出所有文件和文件夹
for file in dirs:
print file
执行结果:
test.htm
stamp
faq.htm
_vti_txt
robots.txt
itemlisting
resumelisting
writing_effective_resume.htm
advertisebusiness.htm
papers
resume
——from:Python os.listdir() 方法 | 菜鸟教程
读取某文件夹下的所有文件如下:
import os
path = "D:/Python34/news" #文件夹目录
files= os.listdir(path) #得到文件夹下的所有文件名称
s = []
for file in files: #遍历文件夹
if not os.path.isdir(file): #判断是否是文件夹,不是文件夹才打开
f = open(path+"/"+file); #打开文件
iter_f = iter(f); #创建迭代器
str = ""
for line in iter_f: #遍历文件,一行行遍历,读取文本
str = str + line
s.append(str) #每个文件的文本存到list中
print(s) #打印结果
注:open(path) 是打开某个文件。ite r是 python 的迭代器。
你也可以把遍历文件夹的操作定义成一个函数,如果是文件夹就不断迭代遍历。进而读取文件夹下所有的文件(包括文件夹里中的文件)
PyInstaller 可以用来打包 python 应用程序,打包完的程序就可以在没有安装Python解释器的机器上运行了。
PyInstaller 支持 Python 2.7 和 Python 3.3+。可以在 Windows、Mac OS X 和 Linux 上使用,但是并不是跨平台的,而是说你要是希望打包成 .exe
文件,需要在 Windows 系统上运行 PyInstaller 进行打包工作;打包成 mac app,需要在 Mac OS 上使用。
1、安装
①Linux or MacOS
你可以从PyPi上下载安装,当然也可以使用 pip 或者 easy_install 来安装。
pip install pyinstaller
or
easy_install pyinstaller
版本更新:
pip install --upgrade pyinstaller
or
easy_install --upgrade pyinstaller
②windows
Windows 上运行 PyInstaller 还需要 PyWin32 或者 pypiwin32,其中 pypiwin32 在你安装 PyInstaller 的时候会自动安装。
使用 pip 安装:pip install pyinstaller
切换到需要打包的目录,执行打包:
pyinstaller dpython.py
执行完毕后,源文件所在目录将生成 dist 和 build 两个文件夹。 其中,build 目录是 pyinstaller 存储临时文件的目录,可以安全删除。最终的打包程序在 dist 内部的 dpython 目录中。目录中其他文件是可执行文件 dpython.exe 的动态链接库。
参数:
参数 | 含义 |
---|---|
-F |
指定打包后只生成一个exe格式的文件 |
-D |
–onedir 创建一个目录,包含exe文件,但会依赖很多文件(默认选项) |
-c |
–console, –nowindowed 使用控制台,无界面(默认) |
-w |
–windowed, –noconsole 使用窗口,无控制台 |
-p |
添加搜索路径,让其找到对应的库。 |
-i |
改变生成程序的icon图标 |
例如使用:pyinstaller -F test.py
打包。
注意如果有引用第三方库的话,这种方法打包的 exe 会提示缺少模块,这时候需要把所有引用的第三方库也一起打包进去:pyinstaller -F -p C:\Users\Lenovo\AppData\Local\Programs\Python\Python36\Lib; test.py
参考及相关阅读:
- 使用 pyinstaller 打包 py 文件成 exe 程序 - SegmentFault 思否
- 超详细Pyinstaller打包exe+反编译Pyinstaller打包的exe教程+防止反编译教程 - 知乎
- pyinstaller简洁教程 | Legendtkl
- 如何使用pyinstaller打包python脚本? - 知乎
代码:
import os
os.chdir("目标目录") #修改当前工作目录
os.getcwd() #获取当前工作目录