1. #encoding=utf-8
    2.
    3. ############# 文件和输入输出 #####################
    4.
    5.
    6. #*********** Part 1: 文件对象 *****************
    7. #文件对象不仅可以用来访问普通的磁盘文件, 而且也可以访问任何其它类型抽象层面上的"文件".
    8.
    9. #随着你使用 Python 经验的增长. 您会遇到很多处理"类文件"对象的情况. 有很多这样的例子,
    10. #例如实时地"打开一个URL"来读取 Web 页面,在另一个独立的进程中执行一个命令进行通讯, 就好
    11. #像是两个同时打开的文件, 一个用于读取, 另个用于写入.
    12. #
    13. #内建函数 open() 返回一个文件对象, 对该文件进行后继相关的操作都要用到
    14. #它. 还有大量的函数也会返回文件对象或是类文件( file-like )对象. 进行这种抽象处理的主要原
    15. #因是许多的输入/输出数据结构更趋向于使用通用的接口. 这样就可以在程序行为和实现上保持一
    16. #致性. 甚至像 Unix 这样的操作系统把文件作为通信的底层架构接口. 请记住, 文件只是连续的字
    17. #节序列. 数据的传输经常会用到字节流, 无论字节流是由单个字节还是大块数据组成.
    18.
    19. #*********** Part 2: 文件内建函数[open()和file()] *****************
    20.
    21. #内建函数 open() [以及 file() ]提供了初始化输入/输出(I/O)
    22. #操作的通用接口. open() 内建函数成功打开文件后时候会返回一个文件对象, 否则引发一个错误.
    23. #当操作失败, Python 会产生一个 IOError 异常,内建函数 open() 的基本语法是:
    24. # file_object = open(file_name, access_mode='r', buffering=-1)
    25.
    26. #file_name 是包含要打开的文件名字的字符串, 它可以是相对路径或者绝对路径. 可选变量
    27. #access_mode 也是一个字符串, 代表文件打开的模式. 通常, 文件使用模式 'r', 'w', 或是 'a'
    28. #模式来打开, 分别代表读取, 写入和追加. 还有个 'U' 模式, 代表通用换行符支持
    29. #
    30. #使用 'r' 或 'U' 模式打开的文件必须是已经存在的. 使用 'w' 模式打开的文件若存在则首
    31. #先清空, 然后(重新)创建. 以 'a' 模式打开的文件是为追加数据作准备的, 所有写入的数据都将
    32. #追加到文件的末尾. 即使你 seek 到了其它的地方. 如果文件不存在, 将被自动创建, 类似以 'w'模式打开文件.
    33. #如果没有给定 access_mode , 它将自动采用默认值 'r' .
    34.
    35. #另外一个可选参数 buffering 用于指示访问文件所采用的缓冲方式. 其中 0 表示不缓冲, 1
    36. #表示只缓冲一行数据, 任何其它大于 1 的值代表使用给定值作为缓冲区大小. 不提供该参数或者
    37. #给定负值代表使用系统默认缓冲机制, 既对任何类电报机( tty )设备使用行缓冲, 其它设备使用正
    38. #常缓冲. 一般情况下使用系统默认方式即可.
    39.
    40.
    41. #文件对象的访问模式
    42. #文件模式 操作
    43. #r 以读方式打开
    44. #rU 或 Ua 以读方式打开, 同时提供通用换行符支持 (PEP 278)
    45. #w 以写方式打开 (必要时清空)
    46. #a 以追加模式打开 (从 EOF 开始, 必要时创建新文件)
    47. #r+ 以读写模式打开
    48. #w+ 以读写模式打开 (参见 w )
    49. #a+ 以读写模式打开 (参见 a )
    50. #rb 以二进制读模式打开
    51. #wb 以二进制写模式打开 (参见 w )
    52. #ab 以二进制追加模式打开 (参见 a )
    53. #rb+ 以二进制读写模式打开 (参见 r+ )
    54. #wb+ 以二进制读写模式打开 (参见 w+ )
    55. #ab+ 以二进制读写模式打开 (参见 a+ )
    56.
    57.
    58. #这里是一些打开文件的例子:
    59. #fp = open('/etc/motd') # 以读方式打开
    60. #fp = open('test', 'w') # 以写方式打开
    61. #fp = open('data', 'r+') # 以读写方式打开
    62. #fp = open(r'c:\io.sys', 'rb') # 以二进制读模式打开
    63.
    64. ############### 工厂函数file()
    65. #open() 和 file() 函数具有相同的功能, 可以任意替换.任何使用 open() 的地方, 都可以使用 file() 替换它.
    66. #一般说来, 建议使用 open() 来读写文件, 在处理文件对象时使用 file() , 例如 if instance(f, file) .
    67.
    68.
    69. ############## 通用换行符支持(UNS)
    70. #Python 2.3 引入了UNS. 当你使用 'U' 标志打开文件的时候, 所有的行分割符(或行结束符, 无论它原来是什么)通过 Python 的输入方法(例
    71. #如 read*() )返回时都会被替换为换行符NEWLINE(\n). ('rU' 模式也支持 'rb' 选项) . 这个特性
    72. #还支持包含不同类型行结束符的文件. 文件对象的newlines 属性会记录它曾“看到的”文件的行结束符.
    73.
    74. #如果文件刚被打开, 程序还没有遇到行结束符, 那么文件的newlines 为 None .在第一行被读
    75. #取后, 它被设置为第一行的结束符. 如果遇到其它类型的行结束符, 文件的newlines 会成为一个
    76. #包含每种格式的元组. 注意 UNS 只用于读取文本文件. 没有对应的处理文件输出的方法.
    77.
    78. #在编译 Python 的时候,UNS 默认是打开的. 如果你不需要这个特性, 在运行configure 脚本
    79. #时,你可以使用 --without-universal-newlines 开关关闭它. 如果你非要自己处理行结束符, 请
    80. #查阅核心笔记,使用 os 模块的相关属性.
    81.
    82.
    83. #*********** Part 3: 文件内建方法 *****************
    84. #open() 成功执行并返回一个文件对象之后, 所有对该文件的后续操作都将通过这个"句柄"进
    85. #行. 文件方法可以分为四类: 输入, 输出, 文件内移动, 以及杂项操作.
    86.
    87. ########### 输入
    88. #read() 方法用来直接读取字节到字符串中, 最多读取给定数目个字节. 如果没有给定 size
    89. #参数(默认值为 -1)或者 size 值为负, 文件将被读取直至末尾. 未来的某个版本可能会删除此方法.
    90.
    91. #readline() 方法读取打开文件的一行(读取下个行结束符之前的所有字节). 然后整行,包括行
    92. #结束符,作为字符串返回. 和 read() 相同, 它也有一个可选的 size 参数, 默认为 -1, 代表读至
    93. #行结束符. 如果提供了该参数, 那么在超过size 个字节后会返回不完整的行.
    94.
    95. #readlines() 方法并不像其它两个输入方法一样返回一个字符串. 它会读取所有(剩余的)行然
    96. #后把它们作为一个字符串列表返回. 它的可选参数 sizhint 代表返回的最大字节大小. 如果它大
    97. #于 0 , 那么返回的所有行应该大约有 sizhint 字节(可能稍微大于这个数字, 因为需要凑齐缓冲区大小).
    98.
    99. ########### 输出
    100. #write() 内建方法功能与 read() 和 readline() 相反. 它把含有文本数据或二进制数据块的
    101. #字符串写入到文件中去.
    102. #
    103. #和 readlines() 一样,writelines() 方法是针对列表的操作, 它接受一个字符串列表作为参
    104. #数, 将它们写入文件. 行结束符并不会被自动加入, 所以如果需要的话, 你必须在调用
    105. #writelines()前给每行结尾加上行结束符.
    106.
    107. #注意这里并没有 "writeline()" 方法, 因为它等价于使用以行结束符结尾的单行字符串调用write() 方法.
    108.
    109. #核心笔记:保留行分隔符
    110. #当使用输入方法如 read() 或者 readlines() 从文件中读取行时, Python 并不会删除行结束
    111. #符. 这个操作被留给了程序员. 例如这样的代码在 Python 程序中很常见:
    112. #f = open('myFile', 'r')
    113. #data = [line.strip() for line in f.readlines()]
    114. #f.close()
    115. #类似地, 输出方法 write() 或 writelines() 也不会自动加入行结束符. 你应该在向文件写入数据前自己完成。
    116.
    117.
    118. ########### 文件内移动
    119. #seek() 方法(类似 C 中的 fseek() 函数)可以在文件中移动文件指针到不同的位置. offset
    120. #字节代表相对于某个位置偏移量. 位置的默认值为 0 , 代表从文件开头算起(即绝对偏移量), 1 代表从当前位置算起, 2 代表从文件末尾算起.
    121. #text() 方法是对 seek() 的补充; 它告诉你当前文件指针在文件中的位置 - 从文件起始算起,单位为字节.
    122.
    123. ########### 文件迭代
    124. #一行一行访问文件很简单:
    125. #for eachLine in f:
    126. #
    127. #在这个循环里, eachLine 代表文本文件的一行(包括末尾的行结束符),你可以使用它做任何想做的事情.
    128.
    129. #文件迭代更为高效, 而且写(和读)这样的 Python 代码更容易.
    130.
    131.
    132. ########### 其它
    133.
    134. #close() 通过关闭文件来结束对它的访问. Python 垃圾收集机制也会在文件对象的引用计数降
    135. #至零的时候自动关闭文件. 这在文件只有一个引用时发生, 例如 fp = open(...), 然后 fp 在原文
    136. #件显式地关闭前被赋了另一个文件对象. 良好的编程习惯要求在重新赋另个文件对象前关闭这个文
    137. #件. 如果你不显式地关闭文件, 那么你可能丢失输出缓冲区的数据.
    138.
    139. #fileno() 方法返回打开文件的描述符. 这是一个整数, 可以用在如 os 模块( os.read() )的
    140. #一些底层操作上.
    141. #调用 flush() 方法会直接把内部缓冲区中的数据立刻写入文件, 而不是被动地等待输出缓冲
    142. #区被写入. isatty() 是一个布尔内建函数, 当文件是一个类 tty 设备时返回 True , 否则返回
    143. #False . truncate() 方法将文件截取到当前文件指针位置或者到给定 size , 以字节为单位.
    144.
    145.
    146. ########### 文件方法杂项
    147.
    148. #filename = input('Enter file name: ')
    149. #f = open(filename, 'r')
    150. #allLines = f.readlines()
    151. #f.close()
    152. #for eachLine in allLines:
    153. # print(eachLine)
    154.
    155. #与大多数标准的文件访问方法相比, 它的不同在于它读完所有的行才开始向屏幕输出数据.
    156. #很明显如果文件很大, 这个方法并不好. 这时最好还是回到最可靠的方法:
    157. #使用文件迭代器, 每次只读取和显示一行:
    158.
    159. #filename = input('Enter file name: ')
    160. #f = open(filename, 'r')
    161. #for eachLine in f:
    162. # print(eachLine)
    163. #f.close()
    164.
    165. #核心笔记: 行分隔符和其它文件系统的差异
    166. #操作系统间的差异之一是它们所支持的行分隔符不同. 在 POSIX (Unix 系列或 Mac OS X)系统
    167. #上, 行分隔符是 换行符 NEWLINE ( \n ) 字符. 在旧的 MacOS 下是 RETURN ( \r ) , 而 DOS 和
    168. #Wind32 系统下结合使用了两者 ( \r\n ). 检查一下你所使用的操作系统用什么行分隔符。
    169. #另个不同是路径分隔符(POSIX 使用 "/", DOS 和 Windows 使用 "\", 旧版本的 MacOS 使用
    170. #":"), 它用来分隔文件路径名, 标记当前目录和父目录.
    171. #当我们创建要跨这三个平台的应用的时候, 这些差异会让我们感觉非常麻烦(而且支持的平台
    172. #越多越麻烦)。幸运的是 Python 的 os 模块设计者已经帮我们想到了这些问题. os 模块有五个很
    173. #有用的属性.
    174.
    175. #有助于跨平台开发的 os 模块属性
    176. #os 模块属性 描述
    177. #linesep 用于在文件中分隔行的字符串
    178. #sep 用来分隔文件路径名的字符串
    179. #pathsep 用于分隔文件路径的字符串
    180. #curdir 当前工作目录的字符串名称
    181. #pardir (当前工作目录的)父目录字符串名称
    182. #不管你使用的是什么平台, 只要你导入了 os 模块, 这些变量自动会被设置为正确的值, 减少了你的麻烦.
    183.
    184.
    185. #print 语句默认在输出内容末尾后加一个换行符, 而在语句后加一个逗号
    186. #就可以避免这个行为. readline() 和 readlines() 函数不对行里的空白字符做任何处理(参见本章
    187. #练习), 所以你有必要加上逗号. 如果你省略逗号, 那么显示出的文本每行后会有两个换行符, 其
    188. #中一个是输入是附带的, 另个是 print 语句自动添加的.
    189.
    190.
    191. #文件对象还有一个 truncate() 方法, 它接受一个可选的 size 作为参数. 如果给定, 那么文
    192. #件将被截取到最多 size 字节处. 如果没有传递 size 参数, 那么默认将截取到文件的当前位置.
    193. #例如, 你刚打开了一个文件, 然后立即调用 truncate() 方法, 那么你的文件(内容)实际上被删除,
    194. #这时候你是其实是从 0 字节开始截取的( tell() 将会返回这个数值 ).
    195.
    196. #######示例一: 输出到文件
    197. #每次从用户接收一行输入, 然后将文本保存到文件中. 由于input()不会保留用户输入的换行符, 调用 write() 方法时必须加上换行符。
    198. #而且, 在键盘上很难输入一个EOF(end-of-file)字符,所以,程序使用句号( . )作为文件结束的标志, 当用户输入句号后会自动结束输入并关闭文件.
    199. #import os
    200. #filename = input('Enter file name: ')
    201. #fobj = open(filename, 'w')
    202. #
    203. #while True:
    204. # aLine = input("Enter a line ('.' to quit): ")
    205. # if aLine != ".":
    206. # fobj.write('%s%s' % (aLine, os.linesep))
    207. # else :
    208. # break
    209. #fobj.close()
    210. #-->
    211. #Enter file name: test.txt
    212. #Enter a line ('.' to quit): Dave come from anqing
    213. #Enter a line ('.' to quit): Dave is good man!
    214. #Enter a line ('.' to quit): Dave love bl
    215. #Enter a line ('.' to quit): .
    216.
    217.
    218. #####示例二:
    219. #以可读可写模式创建一个新的文件(可能是清空了一个现有的文件). 在向文件写入
    220. #数据后, 我们使用 seek() 方法在文件内部移动, 使用 tell() 方法展示我们的移动过程.
    221.
    222. #f = open('test.txt', 'w+')
    223. #print(f.tell())
    224.
    225. #f.write('test line 1\n') # 加入一个长为12 的字符串 [0-11]
    226. ##print(f.tell())
    227. ##13
    228. #f.write('test line 2\n') # 加入一个长为12 的字符串 [12-23]
    229. ##print(f.tell()) # 告诉我们当前的位置
    230. ##-->13
    231. ##print(f.readline())
    232. ##-->test line 1
    233. #
    234. #f.seek(0, 0) # 回到最开始
    235. #print(f.readline())
    236. #
    237. ##print(f.tell()) # 又回到了第二行
    238. ##13
    239. ##print(f.readline())
    240. ##-->test line 2
    241. ##print(f.tell()) # 又到了结尾
    242. ##-->26
    243. #f.close() # 关闭文件
    244.
    245. #文件对象的内建方法列表
    246. #文件对象的方法 操作
    247. #file.close() 关闭文件
    248. #file.fileno() 返回文件的描述符(file descriptor ,FD, 整数值)
    249. #file.flush() 刷新文件的内部缓冲区
    250. #file.isatty() 判断 file 是否是一个类 tty 设备
    251. #file.nexta() 返回文件的下一行(类似于file.readline() ), 或在没有其它行时引发 StopIteration 异常
    252. #file.read(size=-1) 从文件读取 size 个字节, 当未给定 size 或给定负值的时候, 读取剩余的所有字节, 然后作为字符串返回
    253. #file.readintob(buf, size) 从文件读取 size 个字节到 buf 缓冲器(已不支持)
    254. #file.readline(size=-1) 从文件中读取并返回一行(包括行结束符), 或返回最大 size个字符
    255. #file.readlines(sizhint=0) 读取文件的所有行并作为一个列表返回(包含所有的行结束符); 如果给定 sizhint 且大于 0 ,
    256. # 那么将返回总和大约为sizhint 字节的行(大小由缓冲器容量的下一个值决定)( 比如说缓冲器的大小只能为4K 的倍数,如果sizhint 为15k,则最后返回的可能是16k———译者按)
    257. #file.xreadlinesc() 用于迭代, 可以替换 readlines() 的一个更高效的方法
    258. #file.seek(off, whence=0) 在文件中移动文件指针, 从 whence ( 0 代表文件其始, 1 代表当前位置, 2 代表文件末尾)偏移 off 字节
    259. #file.tell() 返回当前在文件中的位置
    260. #file.truncate(size=file.tell()) 截取文件到最大 size 字节, 默认为当前文件位置
    261. #file.write(str) 向文件写入字符串
    262. #file.writelines(seq) 向文件写入字符串序列 seq ; seq 应该是一个返回字符串的可迭代对象; 在 2.2 前, 它只是字符串的列表
    263.
    264.
    265.
    266.
    267. #*********** Part 4: 文件内建属性 *****************
    268. #文件对象除了方法之外,还有一些数据属性. 这些属性保存了文件对象相关的附加数据, 例如
    269. #文件名(file.name ), 文件的打开模式 ( file.mode ), 文件是否已被关闭 ( file.closed), 以及
    270. #一个标志变量, 它可以决定使用 print 语句打印下一行前是否要加入一个空白字符( file.softspace ).
    271.
    272. #文件对象的属性 描述
    273. #file.closed True 表示文件已经被关闭, 否则为 False
    274. #file.encoding 文件所使用的编码 - 当 Unicode 字符串被写入数据时, 它们将自动使用 file.encoding 转换为字节字符串;
    275. # 若file.encoding 为 None 时使用系统默认编码
    276. #file.mode 文件打开时使用的访问模式
    277. #file.name 文件名
    278. #file.newlinesa 未读取到行分隔符时为 None , 只有一种行分隔符时为一个字符串, 当文件有多种类型的行结束符时,
    279. # 则为一个包含所有当前所遇到的行结束符的列表
    280. #file.softspace 为0 表示在输出一数据后,要加上一个空格符,1 表示不加。这个属性一般程序员用不着,由程序内部使用。
    281.
    282.
    283. #*********** Part 5: 标准文件 *****************
    284. #一般说来, 只要你的程序一执行, 那么你就可以访问三个标准文件. 它们分别是标准输入(一
    285. #般是键盘), 标准输出(到显示器的缓冲输出)和标准错误(到屏幕的非缓冲输出). (这里所说的"缓冲
    286. #"和"非缓冲"是指 open() 函数的第三个参数.) 这些文件沿用的是 C 语言中的命名, 分别为
    287. #stdin , stdout 和 stderr . 我们说"只要你的程序一执行就可以访问这三个标准文件", 意思是这
    288. #些文件已经被预先打开了, 只要知道它们的文件句柄就可以随时访问这些文件.
    289.
    290. #Python 中可以通过 sys 模块来访问这些文件的句柄. 导入 sys 模块以后, 就可以使用
    291. #sys.stdin , sys.stdout 和 sys.stderr 访问. print 语句通常是输出到 sys.stdout ; 而内建
    292. #raw_input() 则通常从 sys.stdin 接受输入.
    293. #记得 sys.* 是文件, 所以你必须自己处理好换行符. 而 print 语句会自动在要输出的字符串
    294. #后加上换行符。
    295.
    296.
    297. #*********** Part 6: 命令行参数 *****************
    298. #sys 模块通过 sys.argv 属性提供了对命令行参数的访问。 命令行参数是调用某个程序时除程序名以外的其它参数.
    299.
    300. #argc 和 argv 分别代表参数个数(argumentcount)和参数向量(argument vector). argv 变量代表一个从命令行上输入的各个参数组成的字符
    301. #串数组; argc 变量代表输入的参数个数. 在 Python 中, argc 其实就是 sys.argv 列表的长度,而该列表的第一项 sys.argv[0] 永远是程序的名称.
    302.
    303. #总结如下:
    304. # sys.argv 是命令行参数的列表
    305. # len(sys.argv) 是命令行参数的个数(也就是 argc)
    306.
    307.
    308. #Python 还提供了两个模块用来辅助处理命令行参数. 其中一个(最原始的)是 getopt 模块,
    309. #它更简单些, 但是不是很精细. 而 Python 2.3 引入的 optparse 模块提供了一个更强大的工具,而且它更面向对象.
    310.
    311. #测试程序:argv.py
    312. #import sys
    313. #print('you entered', len(sys.argv), 'arguments...')
    314. #print('they were:', str(sys.argv))
    315.
    316. ##调用argv.py
    317. #$argv.py 76 tales 85 hawk
    318.
    319. #
    320. #命令行参数有用吗? Unix 操作系统中的命令通常会接受输入, 执行一些功能, 然后把结果作为
    321. #流输出出来. 这些输出的结果还可能被作为下一个程序的输入数据, 在完成了一些其它处理后, 再
    322. #把新的输出送到下一个程序, 如此延伸下去. 各个程序的输出一般是不保存的, 这样可以节省大量
    323. #的磁盘空间, 各个程序的输出通常使用"管道"实现到下个程序输入的转换.
    324.
    325. #这是通过向命令行提供数据或是通过标准输入实现的. 当一个程序显示或是发送它的输出到标
    326. #准输出文件时, 内容就会出现在屏幕上 - 除非该程序被管道连接到下一个程序, 那么此时程序的
    327. #标准输出就成为下个程序的标准输入.
    328.
    329.
    330.
    331. #*********** Part 7: 文件系统 *****************
    332. #对文件系统的访问大多通过 Python 的 os 模块实现. 该模块是Python 访问操作系统功能的主
    333. #要接口. os 模块实际上只是真正加载的模块的前端, 而真正的那个"模块"明显要依赖与具体的操作
    334. #系统. 这个"真正"的模块可能是以下几种之一: posix (适用于 Unix 操作系统), nt (Win32),
    335. #mac(旧版本的 MacOS), dos (DOS), os2 (OS/2), 等. 你不需要直接导入这些模块. 只要导入 os 模
    336. #块, Python 会为你选择正确的模块, 你不需要考虑底层的工作. 根据你系统支持的特性, 你可能无
    337. #法访问到一些在其它系统上可用的属性.
    338.
    339. #除了对进程和进程运行环境进行管理外, os 模块还负责处理大部分的文件系统操作, 应用程序
    340. #开发人员可能要经常用到这些. 这些功能包括删除/重命名文件, 遍历目录树, 以及管理文件访问权限等.
    341.
    342. #另一个模块 os.path 可以完成一些针对路径名的操作. 它提供的函数可以完成管理和操作文
    343. #件路径名中的各个部分, 获取文件或子目录信息, 文件路径查询等操作.
    344.
    345. #这两个模块提供了与平台和操作系统无关的统一的文件系统访问方法.
    346.
    347. #os 模块的文件/目录访问函数
    348. #函数 描述
    349. ###文件处理
    350. #mkfifo()/mknod() 创建命名管道/创建文件系统节点
    351. #remove()/unlink() Delete file 删除文件
    352. #rename()/renames() 重命名文件
    353. #*statc() 返回文件信息
    354. #symlink() 创建符号链接
    355. #utime() 更新时间戳
    356. #tmpfile() 创建并打开('w+b')一个新的临时文件
    357. #walk() 生成一个目录树下的所有文件名
    358. #
    359. ###目录/文件夹
    360. #chdir()/fchdir() 改变当前工作目录/通过一个文件描述符改变当前工作目录
    361. #chroot() 改变当前进程的根目录
    362. #listdir() 列出指定目录的文件
    363. #getcwd()/getcwdu() 返回当前工作目录/功能相同, 但返回一个 Unicode 对象
    364. #mkdir()/makedirs() 创建目录/创建多层目录
    365. #rmdir()/removedirs() 删除目录/删除多层目录
    366. #
    367. ###访问/权限
    368. #access() 检验权限模式
    369. #chmod() 改变权限模式
    370. #chown()/lchown() 改变 owner 和 group ID/功能相同, 但不会跟踪链接
    371. #umask() 设置默认权限模式
    372. #
    373. ###文件描述符操作
    374. #open() 底层的操作系统 open (对于文件, 使用标准的内建 open() 函数)
    375. #read()/write() 根据文件描述符读取/写入数据
    376. #dup()/dup2() 复制文件描述符号/功能相同, 但是是复制到另一个文件描述符
    377. #
    378. ###设备号
    379. #makedev() 从 major 和 minor 设备号创建一个原始设备号
    380. #major()/minor() 从原始设备号获得 major/minor 设备号
    381.
    382.
    383.
    384. #os 的子模块 os.path 更多用于文件路径名处理.
    385. #os.path 模块中的路径名访问函数
    386. #函数 描述
    387. #
    388. ###分隔
    389. #basename() 去掉目录路径, 返回文件名
    390. #dirname() 去掉文件名, 返回目录路径
    391. #join() 将分离的各部分组合成一个路径名
    392. #split() 返回 (dirname(), basename()) 元组
    393. #splitdrive() 返回 (drivename, pathname) 元组
    394. #splitext() 返回 (filename, extension) 元组
    395. #
    396. ###信息
    397. #getatime() 返回最近访问时间
    398. #getctime() 返回文件创建时间
    399. #getmtime() 返回最近文件修改时间
    400. #getsize() 返回文件大小(以字节为单位)
    401. #
    402. ###查询
    403. #exists() 指定路径(文件或目录)是否存在
    404. #isabs() 指定路径是否为绝对路径
    405. #isdir() 指定路径是否存在且为一个目录
    406. #isfile() 指定路径是否存在且为一个文件
    407. #islink() 指定路径是否存在且为一个符号链接
    408. #ismount() 指定路径是否存在且为一个挂载点
    409. #samefile() 两个路径名是否指向同个文件
    410.
    411. ##############os 和 os.path 模块例子(ospathex.py)
    412. #encoding=utf-8
    413.
    414. #import os
    415. #for tmpdir in ('/tmp', r'c:\temp'):
    416. # if os.path.isdir(tmpdir):
    417. # break
    418. # else:
    419. # print('no temp directory available')
    420. # tmpdir = ''
    421. #
    422. #if tmpdir:
    423. # os.chdir(tmpdir)
    424. # cwd = os.getcwd()
    425. # print('*** current temporary directory')
    426. # print(cwd)
    427. #
    428. #print('*** creating example directory...')
    429. #os.mkdir('example')
    430. #os.chdir('example')
    431. #cwd = os.getcwd()
    432. #print('*** new working directory:')
    433. #print(cwd)
    434. #print('*** original directory listing:')
    435. #print(os.listdir(cwd))
    436. #
    437. #print('*** creating test file...')
    438. #fobj = open('test', 'w')
    439. #fobj.write('foo\n')
    440. #fobj.write('bar\n')
    441. #fobj.close()
    442. #print('*** updated directory listing:')
    443. #print(os.listdir(cwd))
    444. #
    445. #print("*** renaming 'test' to 'filetest.txt'")
    446. #os.rename('test', 'filetest.txt')
    447. #print('*** updated directory listing:')
    448. #print(os.listdir(cwd))
    449. #
    450. #path = os.path.join(cwd, os.listdir (cwd)[0])
    451. #print('*** full file pathname')
    452. #print(path)
    453. #print('*** (pathname, basename) ==')
    454. #print(os.path.split(path))
    455. #print('*** (filename, extension) ==')
    456. #print(os.path.splitext(os.path.basename(path)))
    457. #
    458. #print('*** displaying file contents:')
    459. #fobj = open(path)
    460. #for eachLine in fobj:
    461. # print(eachLine)
    462. #fobj.close()
    463. #
    464. #print('*** deleting test file')
    465. #os.remove(path)
    466. #print('*** updated directory listing:')
    467. #print(os.listdir(cwd))
    468. #os.chdir(os.pardir)
    469. #print('*** deleting test directory')
    470. #os.rmdir('example')
    471. #print('*** DONE')
    472.
    473.
    474. #*********** Part 8: 永久存储模块 *****************
    475.
    476. ##############pickle 和 marshal 模块
    477. #Python 提供了许多可以实现最小化永久性储存的模块. 其中的一组( marshal 和 pickle )可
    478. #以用来转换并储存 Python 对象. 该过程将比基本类型复杂的对象转换为一个二进制数据集合,
    479. #这样就可以把数据集合保存起来或通过网络发送, 然后再重新把数据集合恢复原来的对象格式.
    480. #这个过程也被称为数据的扁平化, 数据的序列化, 或者数据的顺序化. 另外一些模块
    481. #(dbhash/bsddb, dbm, gdbm, dumbdbm 等)以及它们的"管理器"( anydbm )只提供了 Python 字
    482. #符串的永久性储存. 而最后一个模块( shelve ) 则两种功能都具备.
    483.
    484. #marshal 和 pickle 模块都可以对 Python 对象进行储存转换. 这些模块本身
    485. #并没有提供"永久性储存"的功能, 因为它们没有为对象提供名称空间, 也没有提供对永久性储存对
    486. #象的并发写入访问( concurrent write access ). 它们只能储存转换 Python 对象, 为保存和传输
    487. #提供方便. 数据储存是有次序的(对象的储存和传输是一个接一个进行的). marshal 和 pickle 模
    488. #块的区别在于 marshal 只能处理简单的 Python 对象(数字, 序列, 映射, 以及代码对象), 而
    489. #pickle 还可以处理递归对象, 被不同地方多次引用的对象, 以及用户定义的类和实例. pickle 模
    490. #块还有一个增强的版本叫 cPickle , 使用 C 实现了相关的功能.
    491.
    492. ############## DBM 风格的模块
    493. #*db* 系列的模块使用传统的 DBM 格式写入数据, Python 提供了 DBM 的多种实现:
    494. #dbhash/bsddb, dbm, gdbm, 以及 dumbdbm 等. 你可以随便按照你的爱好使用, 如果你不确定
    495. #的话, 那么最好使用 anydbm 模块, 它会自动检测系统上已安装的 DBM 兼容模块, 并选择"最好"
    496. #的一个. dumbdbm 模块是功能最少的一个, 在没有其它模块可用时, anydbm 才会选择它. 这些模块
    497. #为用户的对象提供了一个命名空间, 这些对象同时具备字典对象和文件对象的特点. 不过不足之处
    498. #在于它们只能储存字符串, 不能对 Python 对象进行序列化.
    499.
    500.
    501. ########## shelve 模块
    502.
    503. #shelve 模块使用 anydbm 模块寻找
    504. #合适的 DBM 模块, 然后使用 cPickle 来完成对储存转换过程. shelve 模块允许对数据库文件进行
    505. #并发的读访问, 但不允许共享读/写访问. 这也许是我们在 Python 标准库里找到的最接近于永久
    506. #性储存的东西了. 可能有一些第三方模块实现了"真正"的永久性储存.
    507.
    508.
    509. #核心模块: pickle 和 cPickle
    510. #你可以使用 pickle 模块把 Python 对象直接保存到文件里, 而不需要把它们转化为字符串,
    511. #也不用底层的文件访问操作把它们写入到一个二进制文件里. pickle 模块会创建一个 Python 语言
    512. #专用的二进制格式, 你不需要考虑任何文件细节, 它会帮你干净利索地完成读写对象操作, 唯一需
    513. #要的只是一个合法的文件句柄.
    514. #pickle 模块中的两个主要函数是 dump() 和 load() . dump() 函数接受一个文件句柄和一个
    515. #数据对象作为参数, 把数据对象以特定格式保存到给定文件里. 当我们使用 load() 函数从文件中
    516. #取出已保存的对象时, pickle 知道如何恢复这些对象到它们本来的格式. 我们建议你看一看
    517. #pickle 和更"聪明"的 shelve 模块, 后者提供了字典式的文件对象访问功能, 进一步减少了程序
    518. #员的工作.
    519. #cPickle 是 pickle 的一个更快的 C 语言编译版本.