发布时间:2018-04-26 19:56:03编辑:Run阅读(3437)
os模块是与操作系统交互的一个接口
使用前需要 import os
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 获取系统环境变量 os.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的大小
递归实现查看当前目录(包含目录下的目录)下所有文件大小的总和
import os def get_size(dir): sum_size = 0 for item in os.listdir(dir): # os.listdir(file)列出指定目录(file)下的所有文件和子目录,包括隐藏文件,并以列表方式打印 path = os.path.join(dir, item) # 将多个路径组合后返回(目录+文件) # print(path) if os.path.isfile(path): # 判断文件是否存在 sum_size += os.path.getsize(path) # os.path.getsize返回文件大小 else: sum_size += get_size(path) return sum_size ret = get_size('D:\python11_quanzhan') print(ret)
执行结果
21581084
用栈(先进后出)的方式查看当前目录(包含目录下的目录)下所有文件大小的总和
import os def get_size(path): l = [path] sum_size = 0 while l: path = l.pop() for item in os.listdir(path): # os.listdir(file)列出指定目录(file)下的所有文件和子目录,包括隐藏文件,并以列表方式打印 path2 = os.path.join(path, item) # 将多个路径组合后返回(目录+文件) if os.path.isfile(path2): # 判断文件是否存在 sum_size += os.path.getsize(path2) # 计算文件大小总和 else: l.append(path2) return sum_size print(get_size('D:\python11_quanzhan'))
执行结果
21581560
模块
1 什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
2 为何要使用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块导入导入到其它的模块中,实现了功能的重复利用
3 如何使用模块?
示例: 新建一个模块名test_module.py,内容如下
print('from the test_module.py') money = 1000 def read1(): print('read1 :', money) def read2(): print('read2----->read1') read1() def change(): global money money = 0
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下,创建一个demo.py文件,导入上面创建的test_module.py文件
import test_module # 导入test_module模块 # 只在第一次导入时才执行test_module.py内代码,此处的显式效果是只打印一次'from the test_module.py' # 当然其他的顶级代码也都被执行了,只不过没有显示效果(没有print) print(test_module.money) # 打印test_module里面的money变量
执行结果
from the test_module.py
1000
我们可以从sys.modules中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
测试一:money与my_module.money不冲突,更改demo.py内容如下
import test_module money = 10 print(money) # 打印自己的(demo.py)全局变量money print(test_module.money) # 打印test_module里面的全局变量money
执行结果
from the test_module.py
10
1000
测试二:read1与test_module.read1不冲突
import test_module def read1(): print('==========') test_module.read1() # 执行test_module里面的read1()函数 read1() # 执行demo里面的read1()函数
执行结果
from the test_module.py
read1 : 1000
==========
测试三:执行test_module.change()操作的全局变量money仍然是test_module中的
import test_module money = 1 test_module.change() print(test_module.money) # test_module中的money print(money) # demo中的money
执行结果
from the test_module.py
0
1
总结:首次导入模块test_module时会做三件事
导入一个模块,相当于这个模块从上到下依次被执行了,同一个模块不会被多次导入
1 为源文件(test_module)创建新的名称空间,在test_module中定义的函数和方法若是使用到了global时,访问的就是这个名称空间
2 在新创建的命名空间中执行模块中包含的代码
3 创建名字test_module来引用该命名空间
为模块名起别名:使用了别名,之前的模块名就不能使用了
import test_module as test print(test.money)
执行结果
from the test_module.py
1000
现在有一个需求,用户可以选择json或者pickle (序列化)
大致代码,并不完善(提供一个思路)
inp = input('json or pickle >>>') if inp == 'json': import json as m elif inp == 'pickle': import pickle as m m.dumps({'k':'v'}) m.loads(...)
在一行导入多个模块
import sys,os,re....
from...import...
对比import test_module,会将源文件的名称空间'test_module'带到当前名称空间中,使用时必须是test_module.(点)名字的方式
而from语句相当于import,也会创建新的名称空间,但是将test_module中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
from test_module import read1,read2
这样在当前位置直接使用read1和read2就好了,执行时,仍然以test_module.py文件全局名称空间
测试一:导入的函数read1,执行时仍然回到test_module.py中寻找全局变量money
还是之前的demo.py和 test_module.py文件中测试
from test_module import read1 money = 2000 read1()
执行结果
from the test_module.py
read1 : 1000
测试二:导入的函数read2,执行时需要调用read1(),仍然回到test_module.py中找read1()
from test_module import read1,read2 def read1(): print('=========') read2()
执行结果
from the test_module.py
read2----->read1
read1 : 1000
测试三: 导入的函数read1,被当前位置定义的read1覆盖了,覆盖效果
from test_module import read1 def read1(): print('==========') read1()
执行结果
from the test_module.py
==========
需要特别强调的一点是:python中的变量赋值不是一种存储操作,而只是一种绑定关系,如下:
from test_module import money,read1 money = 100 # 将当前位置的名字money绑定到了100 print(money) read1() # 读取test_module.py中的名字money,仍然为1000
执行结果
from the test_module.py
100
read1 : 1000
也支持as别名,多行导入
from test_module import read1 as r
from test_module import read1 as r1, read2 as r2, money as m r1() r2() print(m)
执行结果
from the test_module.py
read1 : 1000
read2----->read1
read1 : 1000
1000
from test_module import * 把test_module中所有的不是以下划线 _ ,开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入的名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题
from test_module import * # 将模块test_module中所有的名字都导入到当前名称空间 print(money) print(read1) print(read2) print(change)
执行结果
from the test_module.py
1000
在test_module.py中新增一行,限制导入的范围
__all__=['money','read1'] # 这样在另外一个文件中用from test_module import * 就只能导入列表中规定的两个名字
思考:假如有两个模块a,b。我可不可以在a模块中import b ,再在b模块中import a?
代码不会发现循环引用问题,模块中的引用不能成环
47605
45985
36909
34469
29080
25713
24566
19714
19245
17756
5565°
6155°
5691°
5737°
6705°
5483°
5484°
5988°
5965°
7295°