溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python異步在非阻塞子進(jìn)程中運行命令的方法是什么

發(fā)布時間:2023-03-22 11:21:28 來源:億速云 閱讀:77 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下Python異步在非阻塞子進(jìn)程中運行命令的方法是什么的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

1. 什么是 asyncio.subprocess.Process

我們可以從 asyncio 執(zhí)行命令。該命令將在我們可以使用非阻塞 I/O 寫入和讀取的子進(jìn)程中運行。

asyncio.subprocess.Process 類提供了由 asyncio 運行的子進(jìn)程的表示。它在 asyncio 程序中提供子進(jìn)程的句柄,允許對其執(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í)行子進(jìn)程時,會為我們創(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í)行它。

這很有用,因為它允許命令在子進(jìn)程中執(zhí)行,并允許 asyncio 協(xié)程讀取、寫入和等待它。

與 asyncio.create_subprocess_shell() 函數(shù)不同,asyncio.create_subprocess_exec() 不會使用 shell 執(zhí)行命令。

這意味著 shell 提供的功能,例如 shell 變量、腳本和通配符,在執(zhí)行命令時不可用。

這也意味著執(zhí)行命令可能更安全,因為沒有機(jī)會進(jìn)行 shell 注入。

現(xiàn)在我們知道了 asyncio.create_subprocess_exec() 的作用,讓我們看看如何使用它。

2.1. 如何使用 Asyncio create_subprocess_exec()

asyncio.create_subprocess_exec() 函數(shù)將在子進(jìn)程中執(zhí)行給定的字符串命令。

它返回一個代表子進(jìn)程的 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() 方法來等待子進(jìn)程完成。

...
# wait for the subprocess to terminate
await process.wait()

我們可以通過調(diào)用 terminate() 或 kill() 方法直接停止子進(jìn)程,這將在子進(jìn)程中引發(fā)一個信號。

...
# terminate the subprocess
process.terminate()

命令的輸入和輸出將由 stdin、stderr 和 stdout 處理。我們可以讓 asyncio 程序處理子進(jìn)程的輸入或輸出。

這可以通過指定輸入或輸出流并指定要重定向的常量來實現(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é)為單位設(shè)置“input”參數(shù),通過 communicate() 方法將數(shù)據(jù)發(fā)送到子進(jìn)程。

...
# 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 將子進(jìn)程配置為指向 StreamReader 或 StreamWriter,用于向子進(jìn)程發(fā)送數(shù)據(jù)或從子進(jìn)程發(fā)送數(shù)據(jù),并且 communicate() 方法將從配置的讀取器讀取或?qū)懭胱止?jié)。

我們可以通過子進(jìn)程通過 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 的子進(jìn)程中運行命令。在這個例子中,我們將執(zhí)行“echo”命令來報告一個字符串。

echo 命令將直接在標(biāo)準(zhǔn)輸出上報告提供的字符串。下面列出了完整的示例。

請注意,此示例假設(shè)您可以訪問“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)建子進(jìn)程時掛起。返回一個 Process 實例。

main() 協(xié)程恢復(fù)并報告子進(jìn)程的詳細(xì)信息。 main() 進(jìn)程終止,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 示例包括:

Python異步在非阻塞子進(jìn)程中運行命令的方法是什么

shell 已經(jīng)在運行,它被用來啟動 Python 程序。您無需執(zhí)行任何特殊操作即可獲取或訪問 shell。

我們可以通過 create_subprocess_shell() 函數(shù)從 asyncio 程序執(zhí)行命令。

asyncio.create_subprocess_shell() 函數(shù)接受一個命令并使用當(dāng)前用戶 shell 執(zhí)行它。

這很有用,因為它不僅允許執(zhí)行命令,還允許使用 shell 的功能,例如重定向、通配符等。

該命令將在執(zhí)行 asyncio 程序的進(jìn)程的子進(jìn)程中執(zhí)行。重要的是,asyncio 程序能夠與子進(jìn)程異步交互,例如通過協(xié)程。

通過 shell 而不是直接執(zhí)行命令時,可能會有安全考慮。

這是因為請求執(zhí)行命令和正在執(zhí)行的命令之間至少存在一層間接和解釋,允許可能的惡意注入。

現(xiàn)在我們知道了 asyncio.create_subprocess_shell() 的作用,讓我們看看如何使用它。

3.1. 如何使用 Asyncio create_subprocess_shell()

asyncio.create_subprocess_shell() 函數(shù)將通過當(dāng)前 shell 執(zhí)行給定的字符串命令。

它返回一個表示進(jìn)程的 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() 方法來等待子進(jìn)程完成。

...
# wait for the subprocess to terminate
await process.wait()

我們可以通過調(diào)用 terminate() 或 kill() 方法直接停止子進(jìn)程,這將在子進(jìn)程中引發(fā)一個信號。

命令的輸入和輸出將由 shell 處理,例如標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)錯誤和標(biāo)準(zhǔn)輸出。

我們可以讓 asyncio 程序處理子進(jìn)程的輸入或輸出。

這可以通過指定輸入或輸出流并指定要重定向的常量來實現(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é)為單位設(shè)置“input”參數(shù),通過 communicate() 方法將數(shù)據(jù)發(fā)送到子進(jìn)程。

...
# 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 將子進(jìn)程配置為指向 StreamReader 或 StreamWriter,用于向子進(jìn)程發(fā)送數(shù)據(jù)或從子進(jìn)程發(fā)送數(shù)據(jù),并且 communicate() 方法將從配置的讀取器讀取或?qū)懭胱止?jié)。

我們可以通過子進(jìn)程通過 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 的子進(jìn)程中運行命令。在這個例子中,我們將執(zhí)行“echo”命令來報告一個字符串。

echo 命令將直接在標(biāo)準(zhǔn)輸出上報告提供的字符串。下面列出了完整的示例。

請注意,此示例假設(shè)您可以訪問“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é)程恢復(fù)并報告子進(jìn)程的詳細(xì)信息。 main() 進(jìn)程終止,asyncio 程序終止。

echo 命令的輸出在命令行上報告。這突出顯示了我們?nèi)绾问褂?shell 從 asyncio 程序執(zhí)行命令。

subprocess: <Process 43916>
Hello World

以上就是“Python異步在非阻塞子進(jìn)程中運行命令的方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI