路徑操作: 3.4版本之前: os.path模塊: from os import path p = path.join('/etc', 'sysconfig', 'network') print(type(p), p) print(path.exists(p)) print(path.split(p)) print(path.abspath('.')) p = path.join('o:/', p, 'test.txt') print(path.dirname(p)) print(path.basename(p)) print(path.splitdrive(p)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3.4版本后: 使用pathlib模塊,提供Path對象來操作。包括目錄和文件 pathlib模塊: from pathlib import Path 目錄操作: 初始化: from pathlib import Path p = Path() #當前目錄 P = Path('a', 'b', '、c/d') #當前目錄下的a/b/c/d P = Path('/etc') #根下的etc目錄 路徑拼接和分解: 操作符:/ Path對象 / Path對象 Path對象 / 字符串 或者 字符串 / Path對象 分解: parts 屬性, 可以返回路徑中的每一個部分 joinpath: joinpath(*other) 連接多個字符串到Path對象中 p = Path() >>>PosixPath('.') p = p /'a' >>>PosixPath('a') p1 = 'b' / p >>> 'b/a' p2 = Path('c') >>> PosixPath('c') p3 = p2 / p1 >>>'c/b/a' print(p3.parts) >>>('c', 'b', 'a') p3.joinpath('etc', 'init.d', Path('httpd')) >>>PosixPath('c/b/a/etc/init.d/httpd') 獲取路徑: str 獲取路徑字符串 bytes 獲取路徑字符串的bytes p = Path('/etc') print(str(p), bytes(p)) >>>/etc b'/etc' 父目錄: parent 目錄的邏輯父目錄 parents 父目錄序列,索引0是直接父 p = Path('/a/b/c/d') print(p.parent.parent)#一個parent向上遞歸一次 for x in p.parents: print(x) >>> /a/b/c >>> /a/b >>> /a >>> / name: 目錄的最后一個部分 suffix:目錄中最后一個部分的擴展名 stem:目錄最后一個部分,沒有后綴 suffixes:返回多個擴展名列表 with_suffix(suffix):補充擴展名到尾部,擴展名存在無效 with_name(name):替換目錄最后一個部分並返回一個新的路徑 p = Path('/tmp/test.tar.gz') >>> PosixPath('/tmp/test.tar.gz') print(p.name) >>>test.tar.gz print(p.suffix) >>>.gz print(p.suffixes) >>>['.tar', '.gz'] print('p.stem') >>>test.tar print(p.with_name('test2.tgz')) >>>/tmp p = Path('/tmp/README') >>>PosixPath('/tmp/README') print(p.with_suffix('.txt')) >>>/tmp/README.txt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cwd() 返回當前工作目錄 home() 返回當前家目錄 is_dir() 是否是目錄 is_file() 是否是普通文件 is_symlink() 是否是軟鏈接 is_socket() 是否是socket文件 is_block_device() 是否是塊設備 is_char_device() 是否是字符設備 is_absolute() 是否是絕對路徑 resolve() 返回一個新的路徑,這個新路徑就是當前Path對象的絕對路徑, 如果是軟鏈接則直接被解析 absolute() 也可以獲取絕對路徑,但是推薦使用resolve() exists() 目錄或文件是否存在 rmdir() 刪除空目錄。沒有提供判斷目錄為空的方法 touch(mode = 0o666, exist_ok = True) 創建一個文件 as_uri() 將路徑返回為URI, 例如'file:///etc' mkdir(mode = 0o777, parents = False, exist_ok = False) parents 是否創建父目錄,True等同於mkdir -p False時,父目錄不存在,拋出FileNotFoundError exist_ok參數, False時,路徑存在,拋出FileExistsError;True時,FileExistsError被忽略 iterdir() 迭代當前目錄 p = Path() p /= 'a/b/c/d' >>>PosixPath('a/b/c/d') p.exists() >>>False p.mkdir(parents = True) p.exists() >>>True 目錄創建完成 就存在了 p.mkdir(parents = True) >>>報錯,目錄已經存在 p.mkdir(parents = True, exist_ok = True) >>>exist_ok = True 時,自動忽略目錄存在 不報錯 p /= 'readme.txt' >>> PosixPath('a/b/c/d/readme.txt') p.parent.rmdir() >>>報錯,目錄不是空目錄 p.parent.exists() False p.mkdir() >>>FileNotFoundError p.mkdir(parents = True) >>>PosixPath('a/b/c/d/readme.txt') #遍歷,並判斷文件類型,如果是目錄是否可以判斷其是否為空 for x in p.parents[len(p.parents) -1].iterdir(): print(x, end='\t') if x.is_dir(): flag = False for _ in x.iterdir(): flag = True break print('dir', 'Not Empty' if flag else 'Empty', sep='\t') elif x.is_file(): print('file') else: print('other files') 通配符: p = Path() glob(pattern) 通配給定的模式 rglob(pattern) 通配給定的模式,遞歸目錄 list(p.glob('test*')) >>>[PosixPath('test.py'), PosixPath('test')] list(p.glob('**/*.py'))#遞歸所有目錄等同rglob >>>[PosixPath('test.py'), PosixPath('a/test.py'), PosixPath('a/1.py'), PosixPath('a/b/yy.py'), PosixPath('a/b/x.py')] list(p.rglob('*.py')) >>>[PosixPath('test.py'), PosixPath('a/test.py'), PosixPath('a/1.py'), PosixPath('a/b/yy.py'), PosixPath('a/b/x.py')] 匹配: match(pattern) 模式匹配,成功返回True Path('a/b.py').match('*.py') #True Path('a/b/c.py').match('b/*.py') Path('a/b/c.py').match('a/*.py') Path('a/b/c.py').match('a/*/*.py') Path('a/b/c.py').match('a/**/*.py') Path('a/b/c.py').match('**/*.py') 文件操作: open(mode = 'r', buffering = -1, encoding = None, errors = None, newline = None) 使用方法類似內建函數open,返回一個文件對象 3.5增加的新函數: read_bytes() 以'rb'讀取路徑對應文件,返回二進制流 read_text(encoding = None, errors = None) 以'rt'讀取路徑對應文件,返回文本 Path.write_bytes(data) 以'wb'方式寫入數據到路徑對應文件 write_text(data, encoding = None, errors = None) 以'wt'方式寫入字符串到路徑對應文件 p = Path('content') p.write_bytes(b'hello world') >>>12 p.read_bytes() >>>b'hello world' from pathlib import Path p = Path('d:/z/test.txt') p.write_text('helloworld') print(p.read_text()) with p.open() as f: print(f.read(7)) >>>hellowo os 模塊: os.name windows 是nt,linux是posix os.uname() linux支持顯示 sys.platform windows顯示win32 linux顯示linux os.listdir('d:/z') 返回目錄內容列表 >>>['open.py', 'test.txt'] 創建軟鏈接: ln -s 目錄 ——> 鏈接 os.stat(path, *, dir_fd = None, follow_symlinks = True) path:路徑的string、bytes 或者 fd follow_symlinks: True 返回文件本身信息 False 如果是軟鏈接則顯示軟鏈接本身 win: os.stat('d:/z/test.py') >>>os.stat_result(st_mode=33206, st_ino=8162774324624146, st_dev=1422755607, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1509019785, st_mtime=1509019785, st_ctime=1509019785) linux: os.stat('test.py') >>>os.stat_result(st_mode=33204, st_ino=150041, st_dev=2050, st_nlink=1, st_uid=501, st_gid=501, st_size=12, st_atime=1507072698, st_mtime=1507072694, st_ctime=1507072694) os.chmod(path, mode, *, dir_fd = None, follow_symlinks = True) os.chmod('test', 0o777) os.chown(path, uid, gid)#可以修改文件的屬主、屬組,但需要足夠的權限 shutil模塊: 拷貝文件對象,源文件讀取內容,寫入目標文件中來完成拷貝過程, 這樣容易丟失數據信息,因為根本沒有復制過去,使用python庫shutil(高級文件操作) copy復制: copyfileobj(fsrc, fdst[, length]) 文件對象的復制,fsrc和fdst是open的文件對象,復制內容。fdst要求可寫 length指定了表示buffer的大小 import shutil with open('d:/z/test', 'r+') as f1: f1.write('abcd\n123') f1.flush() with open('d:/z/test1', 'w+') as f2: shutil.copyfileobj(f1, f2) >>>指針直接跳到最后一個字母,不能正常復制 copymode(src, dst, *, follow_symlinks = True) 僅僅復制權限 shutil.copymode('test1', 'test') os.stat('test1') >>> os.stat('test') >>> copystat(src, dst, *, follow_symlinks = True) 復制元數據,stat包含權限 stat test copy(src, dst, *, follow_symlinks = True) copyfile(src, dst, follow_symlinks = follow_symlinks) copyfile(src, dst, follow_symlinks = follow_symlinks) copy2比copy多了復制全部元數據,但需要平台支持 本質上調用的是: copyfile(src, dst, follow_symlinks = follow_symlinks) copystat(src, dst, follow_symlinks = follow_symlinks) copytree(src, dst, symlinks = False, ignore = None, copy_function = copy2, ignore_dangling_symlinks = False) 遞歸復制目錄。默認使用copy2,也就是帶更多的元數據復制 src、dst必須是目錄,src必須存在,dst必須不存在 ignore = func,提供一個callable(src, names) -> ignored_names。提供一個函數,它會被調用。src是源目錄,names是os.listdir(src)的結果, 就是列出src中的文件名,返回值是要被過濾的文件名的set類型數據。 def ignore(src, names): ig = filter(lambda x:x.startswith('a'), names) return set(ig) shutil.copytree('d:/z', 'd:/zz/') rm刪除: shutil.rmtree(path, ignore_errors = False, onerror = None): 遞歸刪除 ignore_errors為true,忽略錯誤。當false活着omitted時onerror生效 onerror為callable,接收函數function、path和execinfo shutil.rmtree('d:/z')#類似rm -rf move移動: move(src, dst, copy_function = copy2) 遞歸移動文件、目錄到目標,返回目標 默認使用copy2方法 os.rename('d:/t.txt', 'd:/z/x.txt') os.rename('test3', 'd:/tmp/test33')