Python異步在非阻塞子進程中運行命令詳解
1. 什么是 asyncio.subprocess.Process
我們可以從 asyncio 執(zhí)行命令。該命令將在我們可以使用非阻塞 I/O 寫入和讀取的子進程中運行。
asyncio.subprocess.Process 類提供了由 asyncio 運行的子進程的表示。它在 asyncio 程序中提供子進程的句柄,允許對其執(zhí)行操作,例如等待和終止它。
該 API 與 multiprocessing.Process 類非常相似,可能與 subprocess.Popen 類更相似。具體來說,它與 subprocess.Popen 共享 wait()、communicate() 和 send_signal() 等方法以及 stdin、stdout 和 stderr 等屬性。
現(xiàn)在我們知道了 asyncio.subprocess.Process 類是什么,讓我們看看如何在我們的 asyncio 程序中使用它。
我們不直接創(chuàng)建 asyncio.subprocess.Process。相反,在 asyncio 程序中執(zhí)行子進程時,會為我們創(chuàng)建一個類的實例。
有兩種方法可以將外部程序作為子流程執(zhí)行并獲取 Process 實例,它們是:
- asyncio.create_subprocess_exec() 用于直接運行命令。
- asyncio.create_subprocess_shell() 用于通過 shell 運行命令。
讓我們依次看一下每個示例。
2. 如何直接運行命令
命令是在命令行(終端或命令提示符)上執(zhí)行的程序。這是另一個直接運行的程序。
Linux 和 macOS 上的常見示例可能是:
- ‘ls’ 列出目錄的內(nèi)容
- ‘cat’報告文件的內(nèi)容
- “data”報告日期
- ‘echo’ 報告一個字符串
- ‘sleep’ 睡眠幾秒鐘
我們可以通過 create_subprocess_exec() 函數(shù)從 asyncio 程序執(zhí)行命令。
asyncio.create_subprocess_exec() 函數(shù)接受一個命令并直接執(zhí)行它。
這很有用,因為它允許命令在子進程中執(zhí)行,并允許 asyncio 協(xié)程讀取、寫入和等待它。
與 asyncio.create_subprocess_shell() 函數(shù)不同,asyncio.create_subprocess_exec() 不會使用 shell 執(zhí)行命令。
這意味著 shell 提供的功能,例如 shell 變量、腳本和通配符,在執(zhí)行命令時不可用。
這也意味著執(zhí)行命令可能更安全,因為沒有機會進行 shell 注入。
現(xiàn)在我們知道了 asyncio.create_subprocess_exec() 的作用,讓我們看看如何使用它。
2.1. 如何使用 Asyncio create_subprocess_exec()
asyncio.create_subprocess_exec() 函數(shù)將在子進程中執(zhí)行給定的字符串命令。
它返回一個代表子進程的 asyncio.subprocess.Process 對象。
create_subprocess_exec() 函數(shù)是一個協(xié)程,這意味著我們必須等待它。它會在子流程啟動后返回,而不是在子流程完成時返回。
... # execute a command in a subprocess process = await asyncio.create_subprocess_exec('ls')
正在執(zhí)行的命令的參數(shù)必須作為后續(xù)參數(shù)提供給 create_subprocess_exec() 函數(shù)。
... # execute a command with arguments in a subprocess process = await asyncio.create_subprocess_exec('ls', '-l')
我們可以通過等待 wait() 方法來等待子進程完成。
... # wait for the subprocess to terminate await process.wait()
我們可以通過調(diào)用 terminate() 或 kill() 方法直接停止子進程,這將在子進程中引發(fā)一個信號。
... # terminate the subprocess process.terminate()
命令的輸入和輸出將由 stdin、stderr 和 stdout 處理。我們可以讓 asyncio 程序處理子進程的輸入或輸出。
這可以通過指定輸入或輸出流并指定要重定向的常量來實現(xiàn),例如 asyncio.subprocess.PIPE。
例如,我們可以將命令的輸出重定向到 asyncio 程序:
... # start a subprocess and redirect output process = await asyncio.create_subprocess_exec('ls', stdout=asyncio.subprocess.PIPE)
然后我們可以通過 asyncio.subprocess.Process 實例通過 communicate() 方法讀取程序的輸出。
此方法是協(xié)程,必須等待。它用于通過子流程發(fā)送和接收數(shù)據(jù)。
... # read data from the subprocess line = process.communicate()
我們還可以通過以字節(jié)為單位設置“input”參數(shù),通過 communicate() 方法將數(shù)據(jù)發(fā)送到子進程。
... # start a subprocess and redirect input process = await asyncio.create_subprocess_exec('ls', stdin=asyncio.subprocess.PIPE) # send data to the subprocess process.communicate(input=b'Hello\n')
在后臺,asyncio.subprocess.PIPE 將子進程配置為指向 StreamReader 或 StreamWriter,用于向子進程發(fā)送數(shù)據(jù)或從子進程發(fā)送數(shù)據(jù),并且 communicate() 方法將從配置的讀取器讀取或寫入字節(jié)。
我們可以通過子進程通過 stdin、stdout 和 stderr 屬性直接與 StreamReader 或 StreamWriter 交互。
... # read a line from the subprocess output stream line = await process.stdout.readline()
現(xiàn)在我們知道如何使用 create_subprocess_exec() 函數(shù),讓我們看一些工作示例。
2.2. Asyncio create_subprocess_exec() 示例
我們可以探索如何在 asyncio 的子進程中運行命令。在這個例子中,我們將執(zhí)行“echo”命令來報告一個字符串。
echo 命令將直接在標準輸出上報告提供的字符串。下面列出了完整的示例。
請注意,此示例假設您可以訪問“echo”命令,我不確定它是否適用于 Windows。
# SuperFastPython.com # example of executing a command as a subprocess with asyncio import asyncio # main coroutine async def main(): # start executing a command in a subprocess process = await asyncio.create_subprocess_exec('echo', 'Hello World') # report the details of the subprocess print(f'subprocess: {process}') # entry point asyncio.run(main())
運行示例首先創(chuàng)建 main() 協(xié)程并將其作為 asyncio 程序的入口點執(zhí)行。
main() 協(xié)程運行并調(diào)用 create_subprocess_exec() 函數(shù)來執(zhí)行命令。
main() 協(xié)程在創(chuàng)建子進程時掛起。返回一個 Process 實例。
main() 協(xié)程恢復并報告子進程的詳細信息。 main() 進程終止,asyncio 程序終止。
echo 命令的輸出在命令行上報告。這突出了我們?nèi)绾螐?asyncio 程序執(zhí)行命令。
Hello World subprocess: <Process 50249>
3. 如何通過 Shell 運行命令
我們可以使用 shell 執(zhí)行命令。shell 是命令行的用戶界面,稱為命令行解釋器 (CLI)。它將代表用戶解釋和執(zhí)行命令。
它還提供諸如用于腳本、通配符、管道、shell 變量(例如 PATH)等的原始編程語言等功能。
例如,我們可以將一條命令的輸出重定向為另一條命令的輸入,比如將“/etc/services”文件的內(nèi)容重定向到word count命令“wc”中,統(tǒng)計行數(shù):
cat /etc/services | wc -l
基于 Unix 的操作系統(tǒng)中的 shell 示例包括:
shell 已經(jīng)在運行,它被用來啟動 Python 程序。您無需執(zhí)行任何特殊操作即可獲取或訪問 shell。
我們可以通過 create_subprocess_shell() 函數(shù)從 asyncio 程序執(zhí)行命令。
asyncio.create_subprocess_shell() 函數(shù)接受一個命令并使用當前用戶 shell 執(zhí)行它。
這很有用,因為它不僅允許執(zhí)行命令,還允許使用 shell 的功能,例如重定向、通配符等。
該命令將在執(zhí)行 asyncio 程序的進程的子進程中執(zhí)行。重要的是,asyncio 程序能夠與子進程異步交互,例如通過協(xié)程。
通過 shell 而不是直接執(zhí)行命令時,可能會有安全考慮。
這是因為請求執(zhí)行命令和正在執(zhí)行的命令之間至少存在一層間接和解釋,允許可能的惡意注入。
現(xiàn)在我們知道了 asyncio.create_subprocess_shell() 的作用,讓我們看看如何使用它。
3.1. 如何使用 Asyncio create_subprocess_shell()
asyncio.create_subprocess_shell() 函數(shù)將通過當前 shell 執(zhí)行給定的字符串命令。
它返回一個表示進程的 asyncio.subprocess.Process 對象。
它與我們在上一節(jié)中看到的 create_subprocess_shell() 函數(shù)非常相似。不過,我們將回顧如何使用該函數(shù)以及如何通過 Process 實例與流程交互(以防您直接跳到本節(jié))。
create_subprocess_shell() 函數(shù)是一個協(xié)程,這意味著我們必須等待它。它會在子流程啟動后返回,而不是在子流程完成時返回。
... # start a subprocess process = await asyncio.create_subprocess_shell('ls')
我們可以通過等待 wait() 方法來等待子進程完成。
... # wait for the subprocess to terminate await process.wait()
我們可以通過調(diào)用 terminate() 或 kill() 方法直接停止子進程,這將在子進程中引發(fā)一個信號。
命令的輸入和輸出將由 shell 處理,例如標準輸入、標準錯誤和標準輸出。
我們可以讓 asyncio 程序處理子進程的輸入或輸出。
這可以通過指定輸入或輸出流并指定要重定向的常量來實現(xiàn),例如 asyncio.subprocess.PIPE。
例如,我們可以將命令的輸出重定向到 asyncio 程序:
... # start a subprocess and redirect output process = await asyncio.create_subprocess_shell('ls', stdout=asyncio.subprocess.PIPE)
然后我們可以通過 asyncio.subprocess.Process 實例通過 communicate() 方法讀取程序的輸出。
此方法是協(xié)程,必須等待。它用于通過子流程發(fā)送和接收數(shù)據(jù)。
... # read data from the subprocess line = process.communicate()
我們還可以通過以字節(jié)為單位設置“input”參數(shù),通過 communicate() 方法將數(shù)據(jù)發(fā)送到子進程。
... # start a subprocess and redirect input process = await asyncio.create_subprocess_shell('ls', stdin=asyncio.subprocess.PIPE) # send data to the subprocess process.communicate(input=b'Hello\n')
在后臺,asyncio.subprocess.PIPE 將子進程配置為指向 StreamReader 或 StreamWriter,用于向子進程發(fā)送數(shù)據(jù)或從子進程發(fā)送數(shù)據(jù),并且 communicate() 方法將從配置的讀取器讀取或寫入字節(jié)。
我們可以通過子進程通過 stdin、stdout 和 stderr 屬性直接與 StreamReader 或 StreamWriter 交互。
... # read a line from the subprocess output stream line = await process.stdout.readline()
現(xiàn)在我們知道如何使用 create_subprocess_shell() 函數(shù),讓我們看一些工作示例。
3.2. Asyncio create_subprocess_shell() 示例
我們可以探索如何使用 shell 在 asyncio 的子進程中運行命令。在這個例子中,我們將執(zhí)行“echo”命令來報告一個字符串。
echo 命令將直接在標準輸出上報告提供的字符串。下面列出了完整的示例。
請注意,此示例假設您可以訪問“echo”命令,我不確定它是否適用于 Windows。
# SuperFastPython.com # example of executing a shell command as a subprocess with asyncio import asyncio # main coroutine async def main(): # start executing a shell command in a subprocess process = await asyncio.create_subprocess_shell('echo Hello World') # report the details of the subprocess print(f'subprocess: {process}') # entry point asyncio.run(main())
運行示例首先創(chuàng)建 main() 協(xié)程并將其作為 asyncio 程序的入口點執(zhí)行。main() 協(xié)程運行并調(diào)用 create_subprocess_shell() 函數(shù)來執(zhí)行命令。
main() 協(xié)程運行并調(diào)用 create_subprocess_shell() 函數(shù)來執(zhí)行命令。main() 協(xié)程恢復并報告子進程的詳細信息。 main() 進程終止,asyncio 程序終止。
echo 命令的輸出在命令行上報告。這突出顯示了我們?nèi)绾问褂?shell 從 asyncio 程序執(zhí)行命令。
subprocess: <Process 43916> Hello World
以上就是Python異步在非阻塞子進程中運行命令詳解的詳細內(nèi)容,更多關于Python異步非阻塞命令運行的資料請關注腳本之家其它相關文章!
相關文章
python代碼實現(xiàn)TSNE降維數(shù)據(jù)可視化教程
今天小編就為大家分享一篇python代碼實現(xiàn)TSNE降維數(shù)據(jù)可視化教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02python實現(xiàn)AHP算法的方法實例(層次分析法)
這篇文章主要給大家介紹了關于python實現(xiàn)AHP算法(層次分析法)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09Python數(shù)據(jù)結構之優(yōu)先級隊列queue用法詳解
queue庫提供了一個適用于多線程編程的先進先出(FIFO)數(shù)據(jù)結構,可以用來在生產(chǎn)者與消費者線程之間安全地傳遞消息或其他數(shù)據(jù),它會為調(diào)用者處理鎖定,使多個線程可以安全而更容易地處理同一個Queue實例.Queue的大小可能受限,以限制內(nèi)存使用或處理,需要的朋友可以參考下2021-05-05Python的Flask框架中實現(xiàn)登錄用戶的個人資料和頭像的教程
這篇文章主要介紹了Python的Flask框架中實現(xiàn)登錄用戶的個人資料和頭像的教程,這也是各個web框架的最基本功能之一,需要的朋友可以參考下2015-04-04Python實現(xiàn)破解12306圖片驗證碼的方法分析
這篇文章主要介紹了Python實現(xiàn)破解12306圖片驗證碼的方法,涉及Python圖片截取、調(diào)用百度識圖及正則截取等相關操作技巧,需要的朋友可以參考下2017-12-12