2017-06-05 62 views
2

我需要在發出命令後在控制檯中顯示結果。處於打開的cmd.exe當但我無法得到同樣的結果與使用subprocess模塊返回的變量無法從stdout中獲得結果,子流程

例如爲:H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject

該命令產生一個加密的證書的值。

到目前爲止我已嘗試(其中cmd是例如以上):

# checking if output is going to stderr 
out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) 
# attempt with Popen 
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()[0] 
# attempt with Popen not using communicate() 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
out = p.stdout.read() 

所有print (out)值是b''

我甚至已經打破了cmd成多個args兩個check_output()Popen(),使得它看起來像:["H:/path/to/openssl.exe", "x509 -in H:/path/to/cert.pem -noout -subject"]

我確實有一種替代方法來實現結果,但這需要運行一個包含以下命令的.bat文件:start cmd /k "... > H:/path/to/temp.txt"其中...是此處討論的命令。這將.exe輸出重定向到一個臨時文件(出於安全目的),我在將內容讀入變量後將其刪除。

支持信息:

如果命令的第一部分是run(.exe文件),它會打開自定義控制檯該程序。該命令的其餘部分在該控制檯中執行,然後該控制檯關閉。但是,如果整個命令系列在cmd.exe控制檯中使用,則輸出將顯示在該控制檯中。因此,爲什麼使用" "作爲.bat的替代方法,因爲它將它作爲整個命令發佈到打開的控制檯。

使用subprocess.Popen(["cmd.exe"])C:\Python36>打開控制檯,我可以發出有問題的命令,並得到我想要的確切結果。我似乎無法抓住pythonically雖然。但是,subprocess.Popen(["cmd.exe", "H:/path/to/openssl.exe"])不執行第二個命令;打開控制檯但不啓動.exe控制檯。

更新:

我能得到一個結果,但我不喜歡我怎麼到了那裏。有一個較短的方式來做到以下幾點:

p = subprocess.Popen("H:/path/to/openssl.exe", stdin=PIPE, stdout=PIPE) 
# b for byte-type requirement 
p.stdin.write(b"x509 -in H:/path/to/cert.pem -noout -subject") 
p.stdin.close() 
out = p.stdout.read() 

我還可以產生結果:

p = os.popen("start cmd /k H:/path/to/openssl.exe -in H:/path/to/cert.pem -noout -subject")

嘗試添加.read()以上,但打印一個空行

+1

一般提示:在'Popen'參數中設置'shell = True'是不安全的。嘗試改爲將'shlex.split(cmd)'作爲第一個參數傳遞給'Popen'。 – Billy

+0

@比利仍然返回'b'''。我試圖找出爲什麼即使使用分割命令,'Popen()'也沒有按照上述「支持信息」中的描述執行第二個命令。 – madeslurpy

+0

@比利更新的問題 – madeslurpy

回答

0

我不習慣在Windows上使用python,但請嘗試以下操作。不要使用shell=True,而不是與此CMD嘗試:

cmd = ["H:/path/to/openssl.exe", "x509", "-in", "H:/path/to/cert.pem", "-noout", "-subject"] 
+0

應該是一個評論,而不是一個答案。 – Billy

+0

由於'Popen()'沒有執行列表中的下一個命令,所以這不起作用 – madeslurpy

0

你試過存儲整個命令作爲原始字符串,並與外殼傳遞=真

cmd = r'H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject' p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = p.communicate() print(out[0]) #for std out print(out[1]) # for std err

編輯:這工作了我用標準錯誤,

print p.communicate()[1]

b'unable to load certificate\r\n3636:error:0D07209B:asn1 encoding routines:ASN1_ get_object:too long:./crypto/asn1/asn1_lib.c:142:\r\n3636:error:0D068066:asn1 en coding routines:ASN1_CHECK_TLEN:bad object header:./crypto/asn1/tasn_dec.c:1281: \r\n3636:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 erro r:./crypto/asn1/tasn_dec.c:380:Type=X509\r\n3636:error:0906700D:PEM routines:PEM _ASN1_read_bio:ASN1 lib:./crypto/pem/pem_oth.c:83:\r\n'

+0

假設你的意思是'print(out [0])'和'print(out [1])'。是的,我都有,並且都是'b'''。這幾乎就像命令沒有被順序執行一樣。我有一個並行問題發佈[這裏](https://stackoverflow.com/questions/44371876/why-is-popen-not-executing-next-command) – madeslurpy

+0

對我而言,發生的事情是,我正在有效地運行openssl.exe,傳遞有效的參數並獲得回報。但是它似乎沒有進入cmd.exe stdout;它停留在openssl.exe中。我需要基本做'C:\ Users \ Me> H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject'並抓住'stdout';當我運行'Popen()'時,它會產生一個結果,但它被放置在CLI之前的一行而不是'stdout'中。 – madeslurpy