subprocess.run不能完全抑制所有控制台输出。

3
使用 stdout=DEVNULLstderr=STDOUTsubprocess.run 无法完全抑制 subinacl.exe 工具的所有输出。
>>> # Do not suppress: OK
>>> subprocess.run('subinacl.exe /service "foo" display', shell=True)
foo - OpenService Error : 1060 The specified service does not exist as an installed service.



Elapsed Time: 00 00:00:00
Done:        1, Modified        0, Failed        1, Syntax errors        0
Last Done  : foo
Last Failed: foo - OpenService Error : 1060 The specified service does not exist as an installed service.

CompletedProcess(args='subinacl.exe /service "foo" display', returncode=0)

>>> # Suppress: Some output is still printed
>>> subprocess.run('subinacl.exe /service "foo" display', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)

Elapsed Time: 00 00:00:00
Done:        1, Modified        0, Failed        1, Syntax errors        0
Last Done  : foo
Last Failed: foo - OpenService Error : 1060 The specified service does not exist as an installed service.

CompletedProcess(args='subinacl.exe /service "foo" display', returncode=0)
>>>

我的猜测是subinacl.exe正在调用另一个进程来打印输出,而这个输出并没有被压制。使用stdout = DEVNULLstderr = STDOUT会使整个处理链的输出被静音吗?

1
这里不需要使用 shell=True,因为你没有运行一个 shell 命令。 - Eryk Sun
1
覆盖标准句柄并不能阻止进程打开控制台的活动屏幕缓冲区(即"CONOUT$")或通过CreateConsoleScreenBuffer创建新的屏幕缓冲区。如果您不想要任何可见输出,您有三个选项: - Eryk Sun
2
(1)使用 creationflags=DETACHED_PROCESS 来运行它,无需控制台会话;在这种情况下,您应将所有未使用的标准句柄重定向到 DEVNULL。 (2)使用 creationflags=CREATE_NO_WINDOW 来分配一个没有窗口的新的控制台会话(即 GetConsoleWindow() 返回 NULL)。 (3)使用 creationflags=CREATE_NEW_CONSOLEstartupinfo=STARTUPINFO(dwFlags=STARTF_USESHOWWINDOW) 来分配一个带有隐藏窗口的新的控制台会话。 - Eryk Sun
对于我的目的来说,以下内容是有效的:stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW - R01k
如果您不打算通过communicate动态读取管道的内容,就不应该使用管道。管道的容量有限(通常为4K)。当管道已满时,写入操作会被阻塞。这可能会阻塞程序的执行。如果您使用空设备,程序可以将内容写入标准输出或标准错误流而无需阻塞。 - Eryk Sun
1个回答

4

基于Eryk Sun的评论,我不得不使用

subprocess.run(
    'subinacl.exe /service "foo" display',
    stdout=subprocess.DEVNULL,
    stderr=subprocess.STDOUT, 
    creationflags=subprocess.CREATE_NO_WINDOW
)

由于它是写入到没有窗口的控制台,因此重定向标准句柄是可选的。将其重定向到空设备可能会提高性能,因为Windows控制台是我使用过的最慢的终端,但是像subinacl.exe这样的程序直接打开“CONOUT $”,而不考虑标准I/O。 - Eryk Sun
此外,如果一个程序可能通过stdin进行交互(例如,需要用户按键的分页输出),还可以将stdin重定向到空设备,这样所有读取操作都会立即返回为空(EOF)。如果它使用"CONIN$"来打开stdin,那么你必须使用creationflags=DETACHED_PROCESS,并希望该程序在打开"CONIN$"失败时能够正确工作,但实际上它会失败,因为没有控制台会话。 - Eryk Sun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接