[英]Python subprocess cannot capture output of Windows program
使用stdout=subprocess.PIPE
阻止輸出到控制台,但不會捕獲任何內容。
>>> import subprocess
>>> proc = subprocess.Popen(['C:\\Users\\me\\program.exe'])
>>> ERROR: please provide an argument
// TRUNCATED USAGE OUTPUT
proc.wait()
0
>>> proc = subprocess.Popen([''C:\\Users\\me\\program.exe''], stdout=subprocess.PIPE)
>>> proc.communicate()
('', None)
我已經嘗試了 stackoverflow 上可用的所有組合。 shell=True
沒有用。 生成子cmd
沒有用。 subprocess.check_output
捕獲任何內容。 我很高興在評論中重試這些命令中的任何一個。
我猜這與程序附加到外殼有關。
這是程序用來輸出的程序集( mcall
只是一個將內存對齊到 16 位的宏)。 我包括這個的原因是以防GetStdHandle
影響事情。
console_write PROC
; rcx MSG
; rdx LEN
prologue
push rcx
push rdx
xor rcx, rcx
mov ecx, [stdout]
mcall GetStdHandle
mov rcx, rax
xor rdx, rdx
pop r8 ; len
pop rdx ; msg
push 0
mov r9, rsp
push 0
mcall WriteConsoleA
pop rcx
pop rcx
epilogue
console_write ENDP
我被這個難住了。 我已經在 Linux 上做過很多次了。 我只是對 Windows 內部了解不夠,無法解決這個問題。 謝謝!
編輯:我嘗試過的其他事情:
管理員(也使用 STDERR 捕獲)
C:\Windows\system32>C:\Python27\python.exe
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> proc = subprocess.Popen(['C:\\Users\\me\\program.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.communicate()
('', '')
STDOUT 文件重定向
>>> import os
>>> os.system('C:\\Users\\me\\program.exe > out.txt')
0
>>> f = open('out.txt', 'r')
>>> f.read()
''
STDERR 文件重定向
>>> import os
>>> os.system('C:\\Users\\me\\program.exe 2>out.txt')
ERROR: please provide an argument
// TRUNCATED USAGE OUTPUT
0
>>> open('out.txt', 'r').read()
''
命令行捕獲失敗(禁止進入 cmd 的輸出,但沒有捕獲任何內容)
program.exe > out.txt
一位同事指出了這個問題。 事實證明, WriteConsole
不能重定向到文件,它只能與控制台句柄一起使用。 [1] [2]
這個StackOverflow 答案給出了如何解決它的大綱。 如果其他人有這個問題,我已經在 Python 中實現了它。
import win32console
import subprocess
import msvcrt
import os
ccsb = win32console.CreateConsoleScreenBuffer()
fd = msvcrt.open_osfhandle(ccsb, os.O_APPEND)
proc = subprocess.Popen(['C:\\Users\\me\\program.exe'], stdout=fd)
proc.wait()
ccsb.ReadConsoleOutputCharacter(100, win32console.PyCOORDType(0,0)) # reads 100 characters from the first line
對我來說更好的解決方案是使用相同的StdHandle
將WriteConsoleA
更改為WriteFile
。
console_write PROC
; rcx MSG
; rdx LEN
prologue
push rcx
push rdx
xor rcx, rcx
mov ecx, [stdout]
mcall GetStdHandle
mov rcx, rax
; Write File
pop r8 ; len
pop rdx ; msg
; unalign for odd number of pushed args
mov rbx, rsp
sub rbx, 8
and rbx, 0Fh
sub rsp, rbx
; args
mov rcx, rax ; handle
xor r9, r9
push 0 ; 1 arg (ununaligns)
sub rsp, 20h ; shadow
call WriteFile
add rsp, 28h ; shadow + arg
add rsp, rbx ; realign
epilogue
console_write ENDP
您是否也嘗試捕獲 stderr ?
proc = subprocess.Popen([''C:\\Users\\me\\program.exe''], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
更新
您可以嘗試在進程運行時逐行讀取輸出,例如:
p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
retcode = p.poll()
print p.stdout.readline()
if retcode is not None:
break
我認為我沒有足夠的代表來建議一個問題可能重復,也沒有評論,所以我將此作為答案發布,因為盡管 douggard 的答案使我在思考上走上了正確的道路,但它實際上並沒有奏效就我而言,我很難找到可行的解決方案。
這里有一個捕獲 CONOUT 並為我工作的答案: https ://stackoverflow.com/a/38749458/1675668
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.