文章目錄
- 系統編程
- 系統工具
- 概述
- sys模塊
- os模塊
- 腳本運行上下文
- 當前工作路徑
- 命令行參數
- shell環境變量
- 標準流
- 文件和目錄工具
- 文件工具
- 目錄工具
- 并行系統工具
- 進程分支
- 線程
系統編程
系統工具
概述
python系統模塊:
模塊名 | 作用 |
---|---|
*sys | 負責導出與怕以后呢解釋器本身相關的組件 |
*os | 包含與python所在底層操作系統相應的變量和函數 |
*os.path | 為文件和目錄處理工具提供了可移植的接口 |
glob | 用于文件名擴展 |
socket | 用于網絡連接和進程間通信 |
threading,_thread,queue | 用于運行和同步化并發線程 |
subprocess,multiprocessing | 用于啟動和控制并行進程 |
signal,select,shutil,tempfile | 用于多種系統相關任務 |
第三方擴展 | 以下 |
pySerial | 串行端口接口 |
Pexpect | 用于控制程序間對話 |
Twisted | 網絡框架 |
獲取模塊文檔:
-
獲取屬性:dir()
-
獲取用法:
__doc__
或help()
sys模塊
工具 | 作用 |
---|---|
*sys.platform | 底層操作系統名稱 |
sys.maxsize | 當前計算機可容納的最大整型 |
sys.version | python解釋器版本號 |
*sys.path | 正在運行的python解釋器真正的模塊搜索路徑 |
包含代表腳本主目錄的指示器(首項),交互模式下是空字符串 | |
可以更改,并不是永久性的 | |
*sys.modules | 字典,python進程所導入的每一個模塊 |
sys.getrefcount | 查看對象的引用次數 |
sys.builtin_module_names | python可執行程序的內置模塊名稱 |
sys.exc_info() | 元祖,最近異常的類型,值,追蹤對象 |
追蹤對象可用模塊traceback處理 | |
將追蹤對象傳入traceback.print_tb() | |
sys.argv | 命令行參數 |
stdin,stdout,stdrrr | 標準流 |
sys.exit | 強制退出 |
os模塊
提供了POSIX(可移植操作系統接口)工具,不依賴平臺的目錄處理,os.path
常用的os工具:
任務 | 工具 |
---|---|
shell變量 | os.environ:設置和獲取shell環境變量 |
運行程序 | os.execv |
os.execlp:啟動新程序 | |
os.spawnv:啟動帶有底層控制的新程序 | |
os.system():在pythin腳本中運行shell命令,會暫停它的調用者,可在命令后加& | |
os.popen():運行shell命令并與其輸入流(傳入’w’參數,write()方法)或輸出流(默認,read()方法)相連接. | |
os.startfile():用相應的軟件打開文件,無論文件是什么 | |
派生程序 | os.waitpid,os.kill |
os.fork:在類Unix系統下派生新的子進程 | |
os.pipe:負責進程間通信 | |
文件描述符,文件鎖 | os.resd,os.write |
os.open:打開基于底層描述符的文件 | |
os.stat:獲取文件底層信息 | |
文件處理 | os.rename,os.rmdir |
os.walk:將函數和循環運用與整個目錄樹的各部分 | |
os.remove:根據路徑名刪除文件 | |
os.mkdir:創建新目錄 | |
os.mkfifo:創建新的命名管道 | |
管理工具:提供信息,幫助管理 | os.chmod,os.listdir,os.access |
os.getpid():給出掉用函數的進程的id | |
os.getcwd():返回當前目錄 | |
os.chdir():改變目錄 | |
移植工具 | os.path.split(‘path’):將路徑分割為目錄和文件 |
os.path.splitext(‘path’):分割了文件的擴展名 | |
os.path.normpath(‘path’:將路徑分隔符統一為平臺的目錄分隔符) | |
os.path.abspath(‘path’):返回文件的完整目錄路徑名.如添加前綴和處理…語法 | |
os.path.join:將目錄和文件合成路徑 | |
os.path.dirname(‘path’)/basename(‘path’):返回目錄/文件 | |
os.sep:目錄分割符號 | |
os.pathsep:目錄列表中分隔目錄的符號 | |
os.pardir:父目錄 | |
os.curdir:當前目錄 | |
os.linesep:換行符 | |
路徑名工具 | os.path.getsize(‘path’):通過文件名獲取文件大小 |
os.path.isdir(‘path’)/isfile(‘path’):檢測文件類型,是目錄/文件 | |
os.path.exists(‘path’):測試文件是否存在 |
腳本運行上下文
當前工作路徑
當前工作路徑(CWD)與腳本所在路徑區別:
- 當前工作路徑(CWD):
- 當前工作路徑是啟動腳本的路徑,即輸入命令行的地方.
- 腳本中沒有路徑的文件名將會映射到此.
- 通過os.getcwd()獲得,os.chdir()改變.
- 當通過圖標執行一個腳本時,cwd會被設置為腳本所在路徑.
- 腳本所在路徑:
- 腳本所在路徑是腳本文件物理存儲位置.
- import導入時,最先搜索的目錄.
- 可以通過sys.path列表中的首項看到.
命令行參數
sys.argv:得到命令行參數列表.sys.argv[0]為執行腳本的名稱,在命令行出現的順序決定列表中的索引
python中的命令行處理工具解析更復雜的命令行:
- getopt模塊
- optparse模塊,功能更強大
note:
unix上的可執行腳本:
腳本第一行#!/usr/bin/env指定解釋器
chmod u+x scripname:增加可執行權限
shell環境變量
python通過一個類似python字典的對象os.environ訪問環境變量
獲取環境變量:
- os.environ[‘環境變量名’],例如獲取PYTHONPATH:os.environ[‘PYTHONPATH’]
修改環境變量:
-
通過對os.environ[‘環境變量名’]賦值,在內部調用os.putenv改變環境變量(修改是臨時的,只對程序本身和子程序有效)
-
子程序:由Unix下的os.spawnv,os.fork/exec,以及所有平臺的os.popen,os.system,subprocess啟動的程序
-
修改是臨時的原因:一個子程序始終從父程序繼承環境變量,而子程序的環境變量不會傳遞給父進程.
-
標準流
標準流是預先打開的文件對象,python啟動時被綁定到控制臺窗口,sys模塊提供了標準輸入(sys.stdin),標準輸出(sys.stdout)和錯誤流(sys.stderr)
重定向流到文件或程序(依賴shell命令行):
-
標準輸入流重定向到文件輸入:
< fielname
-
標準輸出流重定向到文件:
>filename
-
結合使用:
< inputfile > outputfile
-
管道,一個程序的標準輸出發送到另一個程序的標準輸入,python腳本可以在任意一端:
|
重定向流與用戶交互:
-
當輸入流被重定向后,linux中可以通過/dev/tty文件(當前虛擬終端)讀取鍵盤輸入
-
文件的isatty()方法探測文件是否連接到控制臺
重定向流到python對象:
-
任何提供了類似文件read方法的對象可以指定給sys.stdin,以從該對象的read方法讀取輸入
-
任何定義了類似文件write方法的對象可以指定給sys.stdout,所有標準輸出將發送到該對象方法上
-
需要保存和重置原來的流
io標準庫:
```python
from io import StringIO, BytesIO# StringIO提供對象,將文件對象接口和內存字符串相映射(文本)buff = StringIO() # 在字符串中保存寫入的文本
buff.write('string\n')
buff.getvalue() # 取出值buff = StringIO('string\nstream\n') # 從字符串中讀取輸入值
buff.readline() # ByteIO提供對象,將文件操作映射到內存字節緩沖區(二進制)stream = BytesIO() # 在字節緩沖區中保存寫入的文本
stream.write(b'stream')
stream.getvalue()stream = BytesIO(b'stream') # # 從字節緩沖區中讀取輸入值
stream.read()
```
print調用中的重定向語法:
- print(string, file=filename) #filename為文件名,需要打開的,有寫入權限的
subprocess模塊:
-
運行命令的替代方案,對流的控制更完善,控制的是子程序的流.
-
subprocess.call(‘cmd’,shell=True),shell與平臺相關,類Unix上為真時,由shell執行程序,否則由os.execvp運行
-
將stdout流與管道連接,然后用communicate來運行命令,并接收它的標準輸出流和錯誤流文件
from subprocess import Popen, PIPEpipe = Popen('python hello.py', stdout=PIPE, stdin=PIPE) # 獲取派生程序的輸出流和輸入流 pipe2 = Popen('python reader.py', stdin=pipe.stdout) # 將pipe的輸出流給pipe2的輸入流 pipe.stdin.write('string') #寫入輸入流 pipe.stdin.close() # 關閉輸入流文件 pipe.stdout.read() # 讀取輸出流# pipe.communicate() # # pipe.returncode # 查看退出狀態,成功一般是0 pipe.wait() # 退出狀態
os.popen:
```python
import ospipe = os.popen('python hello_out.py') # 默認對stdout讀
pipe.read()
print(pipe.close()) # None代表沒有錯誤pipe = os.popen('python hello_in.py', 'w') # 對stdin寫
pipe.write('Gumby')
pipe.close()
```
文件和目錄工具
文件工具
內建文件對象
-
支持多種方法:將緩沖區寫入磁盤(‘flush’),釋放系統資源( ‘close’),獲取底層文件句柄(‘fileno’),讀取數據(‘read’, ‘readline’, ‘readlines’),移動到文件的任意位置(‘seek’),返回當前位置(‘tell’),寫入數據(‘writable’, ‘write’, ‘writelines’)
-
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
-
file:文件名,也可以是文件描述符
-
mode:r可讀(默認);w可寫,并擦除以前任何內容;a追加;+可讀可寫;b以二進制方式打開
-
buffering:0無緩存,二進制模式;1逐行緩沖;其他全緩沖(默認)
-
encoding:編碼設置
-
-
seek(N, whence=0)
-
0:絕對的開始位置,偏移量非負
-
1:相對前位置,偏移量可正可負
-
2:絕對的末尾位置,偏移量一般為負
-
用struct模塊解析打包的二進制數據:
import struct # 導入包
data = struct.pack('>i4shf', 2, 'spam', 3, 1.234) # 按照特定格式打包,>表示高位優先,i是四字節整數,4s代表四字節字符串,h是二字節整數,f是浮點數
value = struct.unpack('>i4shf', data) # 按照同樣的格式解包
os模塊中的底層文件工具
-
os.open(path, flags, mode):打開文件并返回其描述符.描述符是整數代碼或句柄,用來標識文件,mode是模式標識符,提供更多的底層控制.
-
O_EXCL:唯一訪問權
-
O_NONBLOCK:非阻塞模式
-
(os.O_RDWR|os.O_BINARY):相當與rb+
-
-
os.read(descriptor, N):最多讀取N個字節并返回一個字節字符串,descriptor是描述符.
-
os.write(descriptor, string):把字節字符串string中的字節寫入文件.
-
os.lseek(descriptor, position, how):在文件中移至position,how相當與seek中的模式.
-
os.fdopen(descriptor, ‘rb’):將文件描述符封裝成文件對象,第二個參數是文件對象模式
-
其他os模塊文件工具
-
os.chmod(filepath, Ooxxx):更改文件權限.文件路徑和三位八進制(與Unix下文件設置相同)
-
os.renaem(oldname, newname):更改名稱
-
os.remove(filename):刪除文件
-
os.stat:(fielname):文件的底層信息
目錄工具
遍歷目錄
-
os.popen():運行shell列表命令,例如unix中ls,windows中dir.與命令耦合,不跨平臺
-
glob.glob()模塊:接受路徑文件名(每一級路徑都可以)模式擴展(?單個字符,*任意個字符,[]字符選集),返回一個匹配文件名(帶前綴路徑)組成的列表.
-
os.listdir():接受路徑目錄名,返回該目錄下所有文件名(不帶路徑前綴)列表.
-
golb和walk都都通過調用listdir實現.
-
如果文件名有特殊字符,可以通過傳入字節字符串(b’…').
-
文件名編碼:os.getfilesystemencoding()
-
遍歷目錄樹
- os.walk():接受一個路徑目錄名,返回一個生成器,為該目錄及其每一個遞歸子目錄下產生一個包括(當前目錄名稱,子目錄列表,文件列表)的三元組.用topdown=False參數可以自底向上遍歷.刪除返回的元祖里子目錄列表中的名稱,可以對目錄樹的枝干進行修剪.
并行系統工具
進程分支
os.fork():
-
啟動新的并行子進程(內存中原來進程的一個副本),在子進程中返回0,在父進程中返回pid
-
os.getpid()獲得當前進程的pid
-
全局對象在子進程開始是有相同的值,全局內存是被復制而不是共享,只改變自己的副本.
-
子進程可以通過顯是的調用os._exit(0)退出
fork和exec組合:
-
os.execlp():用一個全新的程序覆蓋執行原來的程序,通過fork啟動子進程再exec覆蓋,開啟一個與原程序并行運行的新程序,但pid不變
-
exec系列:
-
execv(program, commandlinesequence):參數為可執行程序的名稱(完整路徑),命令行參數字符串組成的列表或元組(在shell中輸入的命令)
-
execl(program, argv0, argv1, …, argvN):參數形式傳入命令行參數
-
excelp,excevp:用系統搜索路徑定位可執行程序(不需要完整路徑)
-
execve,execle:在最后添加一個字典參數,包含發送給程序的shell環境變量
-
execvpe,execlpe:使用搜索路徑并且接受shell環境變量字典參數
-
例子:
os.execlp('python', 'python', 'child.py', str(parm))
-
線程
在同一個進程中,和程序的其他部分并行的調用函數(或其他可調用對象),常用于非阻塞的輸入調用和GUI中長時間的任務.
特點:
-
相對與分支進程開銷小,進程適合計算密集型操作,線程適合IO密集型操作
-
共享全局內存(對象和命名空間4),要仔細控制共享項目的訪問權
-
全局解釋器鎖(GIL):同一時間只有一個線程運行python代碼,不能利用多核
_thread模塊:
-
_thread.start_new_thread():
-
開始一個新線程,接受一個函數(或其他可調用對象,如lambda函數,對象方法)和一個參數元組,返回一個無用值.
-
線程在其運行的函數返回后退出,或主線程退出后隨之退出.
-
線程出現異常不影響程序其他部分的運行.
-
-
同步訪問共享對象和名稱:
-
鎖:要修改一個共享對象,線程 需要獲得一把鎖,然后修改,之后釋放鎖給其他線程獲取.確保任何時間只有一個線程持有鎖.
-
_thread.allocate_lock():創建全局鎖對象,_thread.exit():線程退出
-
全局鎖對象的acquire()方法獲取鎖,release()方法釋放鎖,之間是需要互斥的操作
-
locked()方法檢測鎖是否被獲取,被獲取返回true
-
-
等待派生線程退出(線程通信)
-
鎖列表:創建一個鎖列表,通過為每一個子線程結尾獲取一把鎖,判斷每一把鎖是否都被獲取,則說明子線程都已經結束,就可以退出主線程.
-
整數列表:創建一個列表,每一個子線程結尾都改變其值,通過判斷是否每一個值都改變了,得知子線程是否都結束.可在主線程中用time.sleep()暫停等待子線程結束
-
-
上下文管理
- with mutex(全局鎖對象):自動上鎖和解鎖
threading模塊:
-
基于對象和類的較高層面的接口,內部使用_thread實現
-
可以通過繼承threading.Thread對象定制帶有狀態(初始化方法)和run()行為(提供線程邏輯業務)的線程類.
-
threading.Lock():創建全局鎖對象.全局鎖對象的acquire()方法獲取鎖,release()方法釋放鎖,之間是需要互斥的操作
-
線程類對象的start()方法:在線程中運行run方法.join():等待直到線程退出.如果任何一個派生線程(守護線程除外)還在運行中,程序不會退出.線程類對象的daemon屬性=True可設為守護線程
-
threading.Thread對象接受傳給target參數的調用對象和任意傳給args參數(默認(),代表無)
-
threading模塊還有Semaphore, Condition和Event等
queue模塊:
-
線程程序由一系列消費者程序和一系列生產者程序組成,通過將數據存入一個共享的隊列或從中取出來進行通信,保證線程安全.隊列同步化的是數據傳遞,某些操作仍然需要為其他目的而使用鎖.
-
queue.Queue(maxsize = 0)創建一個隊列對象.maxsize可限制隊列大小,默認無限制.
-
queue.LifoQueue(maxsize = 0)創建一個棧隊列對象
-
queue.PriorityQueue(maxsize = 0)創建一個優先級隊列.典型加入的元素是一個元祖(優先級, 數據),優先級數越小,級別越高
-
queue.deque(maxsize = 0)創建一個雙線隊列
-
queue.empty異常,queue.Full異常:隊列空取,隊列滿存產生的異常
-
隊列對象(例如Queue)的put(item, block=True, timeout=None)方法向隊列中存入數據.如果滿,blocking = False 直接報 Full異常。如果blocking = True,就是等一會,timeout必須為 0 或正數。None為一直等下去,0為不等,正數n為等待n秒還不能存入,報Full異常
-
Queue.get()方法從隊列中取出數據,參數類似put
-
Queue.empty(),Queue.full():判斷隊列是否為空,為滿
-
Queue.task_done():表示隊列中某個元素被消費進程使用,消費結束發送的信息
-
Queue.join():一直阻塞直到隊列中的所有元素都被取出和執行
GUI與線程:
- GUI程序一般采用主GUI線程加一到多個長時間運行的生產者線程,主線程更新界面,每個生產者線程執行一個長時間任務.所有線程共享一個隊列,非GUI線程顯示結果,GUI線程消耗它們.