簡體   English   中英

為什么python.subprocess 在proc.communicate() 之后掛起?

[英]why does python.subprocess hang after proc.communicate()?

我有一個名為my_own_exe的交互式程序。 首先,它打印出alive ,然后你輸入S\\n然后它再次打印出alive 最后你輸入L\\n 它進行一些處理並退出。

但是,當我從以下 python 腳本調用它時,該程序似乎在打印出第一個 'alive' 后掛起。

這里有人能告訴我為什么會這樣嗎?

// 閱讀完后續(謝謝大家)后,我修改了代碼如下:

import subprocess
import time

base_command = "./AO_FelixStrategy_UnitTest --bats 31441 --chix 12467 --enxutp 31884 --turq 26372 --symbol SOGN --target_date " + '2009-Oct-16'
print base_command

proc2 = subprocess.Popen(base_command, shell=True , stdin=subprocess.PIPE,)

time.sleep(2);
print "aliv"
proc2.communicate('S\n')

print "alive"
time.sleep(6)

print "alive"
print proc2.communicate('L\n')
time.sleep(6)

該程序現在與第一個輸入 'S\\n' 運行良好,但隨后停止,而第二個 'L\\n' 有點被忽略。

誰能告訴我為什么會這樣?

用於communicate文檔

與進程交互:將數據發送到標准輸入。 從 stdout 和 stderr 讀取數據,直到到達文件結尾。 等待進程終止。

因此,在communicate()運行后,該進程已終止

如果您想在不等待進程停止的情況下進行寫入和讀取:

  • 永遠不要使用shell=True - 它不必要地調用一個 shell 來調用你的程序,所以你和你的程序之間會有另一個進程。 這有很多令人不快的副作用。 默認是shell=False所以你應該堅持下去。 將您的Popen行更改為:

     p = subprocess.Popen(["./AO_FelixStrategy_UnitTest", "--bats", "31441", "--chix", "12467", "--enxutp", "31884", "--turq", "26372", "--symbol", "SOGN", "--target_date", '2009-Oct-16'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  • 使用p.stdin.write寫入進程。 使用p.stdout.read從中讀取。

  • 如果沒有要讀取的內容,則調用p.stdout.read會阻塞。 如果寫入緩沖區已滿,則調用p.stdin.write將阻塞。 所以你必須確保你有一些東西可以讀/寫 - 你可以在 unix OS 上使用select做到這一點。 不幸的是,在 Windows 上,您必須求助於線程。 至少這是Popen.communicate在內部所做的。
  • 如果您沒有編寫AO_FelixStrategy_UnitTest那么您可能會遇到其他問題:
    • 它可能是從其他地方讀取,而不是標准輸入。 有些程序直接從終端讀取,有些程序使用一些 OS API 來讀取。 這意味着寫入 stdin 的數據不會進入程序。 對於密碼提示,這通常是正確的。
    • 請記住,您必須考慮AO_FelixStrategy_UnitTest緩沖區。 默認情況下,標准 C PIPE 通信是緩沖的,因此在關閉輸入端之前您可能看不到任何輸出(通過執行p.stdin.close() 。除非AO_FelixStrategy_UnitTest定期刷新輸出。

這是一些示例代碼,基於您的描述。 它可以根據AO_FelixStrategy_UnitTest開發方式工作:

p = subprocess.Popen(["./AO_FelixStrategy_UnitTest",
                      "--bats", "31441", "--chix", "12467",
                      "--enxutp", "31884", "--turq", "26372",
                      "--symbol", "SOGN", "--target_date", '2009-Oct-16'],
                     stdin=subprocess.PIPE, 
                     stdout=subprocess.PIPE)
output = p.communicate('S\nL\n')[0]
print output

communicate()從標准輸出和標准錯誤讀取數據,直到到達文件結尾 - 它一直等到你的程序退出。

comunicate只會運行一次,然后會關閉管道,因此如果您想向它發送多個命令,您需要在同一個字符串中一個接一個地發送。

這是經過一些調查后對我有用的示例,嘗試了線程、subprocess32、stdin.write、stdout.read 等。此信息不在用於通信的官方 python 參考信息中: https ://docs.python.org/ 2/library/subprocess.html

我發現這一點的唯一地方是在這里: Python subprocess communication kills my process

這是代碼,它很簡單,沒有線程,沒有 subprocess32,適用於 linux 和 windows。 是的,您必須知道向另一個進程發送命令的次數,但通常您確實知道這一點。 在此之上,您可以添加線程、cwd、shell=True 或您可能想要的任何其他內容,但這是最簡單的情況:

def do_commands(self, cmd, parms):
    proc = subprocess.Popen(cmd,  stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE )

    # wait for the process to terminate
    out, err = process.communicate(cmd_parms)
    errcode = process.returncode

    return errcode, out, err

因此,例如,如果您想向被調用的應用程序發送多個回車符 (\\n) 以及中間的 a 參數(交互式地提醒您),您可以這樣稱呼它:

cmd_parms = "\n\n\n\n\nparm\n\n"

errcode, out, err = do_commands(command, cmd_parms)

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM