如何同时重定向输出并为子进程保留控制台窗口?

huangapple go评论69阅读模式
英文:

How to both redirect output and have a console window for a subprocess?

问题

I want to use subprocess.Popen(["start", "/wait", "program"], shell=True) to have my program open in a new window. At the same time, I want to be able to capture output (stdout), for example by using subprocess.PIPE. However, if I simply add the pipe directive (stdout=.. in popen), the pipe is of the start program which prints nothing.

I tried to follow https://stackoverflow.com/questions/60275345/how-to-redirect-output-from-start-ed-console and use:

v = ["start", "/wait", "program", "^>1"]

but it didn't work (hangs on readline).

I know I can use a log file, but kind of inclined against (because of buffering mainly).

英文:

I want to use
subprocess.Popen(["start", "/wait", "program"], shell=True) to have my program open in a new window. At the same time, I want to be able to capture output (stdout), for example by using subprocess.PIPE. However, if I simply add the pipe directive (stdout=.. in popen) , the pipe is of the start program which prints nothing.

I tried to follow https://stackoverflow.com/questions/60275345/how-to-redirect-output-from-start-ed-console and use :

            v = ["start" ,"/wait", "program", "^>1"]

but it didn't work (hangs on readline).

I know I can use log file, but kind of inclined against (because of buffering mainly).

答案1

得分: 2

start命令将尝试启动名为program的任何程序作为新进程,如果program是基于控制台的,则将为其打开一个新的控制台窗口以将输出(和错误)写入,并可能接收输入。

假设您的应用程序program是基于控制台的,它只有一个stdout流,控制台窗口将接收并在窗口上回显该流。

如您所发现,重定向start命令本身的stdout是无效的,因为它实际上不会将任何内容写入标准输出(当一切正常时)- 它只是用于启动其他程序。

例如,如果您尝试了这样的操作:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t

... 您将在一个新的控制台中看到输出,并且在调用窗口/进程中将看不到任何内容。

如果您尝试像这样重定向输出:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t > test.txt

... 那也不会起作用,因为它只会重定向start的输出,而start的输出是空的。

但是这也行不通:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t ^> test.txt

... 因为没有东西可以应用转义的重定向。这就是为什么您链接的问题建议这样做的原因:

start /wait cmd /c C:\Windows\system32\PING.EXE 8.8.8.8 -t ^> test.txt

这几乎起作用了,它启动了进程,打开了窗口并运行了程序,并将输出捕获到一个文件中。但所有这些都是从新进程中完成的,而不是从调用进程中完成的。

然而,您希望program的文本仍然显示在新的控制台窗口中,并且可以实时访问相同的输出以在脚本中使用(在您的情况下,不是将其重定向到文件中,而是可能以其他方式使用它)。

您可以通过在新控制台中使用PowerShell启动命令来接近此目标,使用Start-Process而不是cmd /c,并使用类似于Linux的tee命令的Tee-Object

然而,这只能在新控制台中同时将输出写入文件和控制台,所有这些都是从新控制台完成的。当然,您可以从您的Python脚本中监视文件的更改,但这仍然只会在Tee-Object将文件缓冲区刷新到磁盘时获取新数据。我认为在Windows中使用普通控制台窗口是无法使其正常工作的,这纯粹是由于它们的工作方式以及您无法仅使用控制台窗口将流从一个进程重定向到另一个进程。

在这里的解决方案可能是编写一个在新控制台窗口中运行的Python脚本,既将数据回显到控制台,又对其进行处理。您只需从原始脚本中启动此辅助脚本,效果就是您需要的。您可能需要提供更多详细信息来解释为什么在您的情况下这不是一个合适的解决方案。

英文:

The start command will try to start whatever program is as a new process and if program is console-based, a new console window will open for it to write output (and errors) to and possibly receive input from.

Assuming your application program is console-based, it only has a single stdout stream, which the console window will receive and echo on the window.

As you found, redirecting the stdout of the start command itself doesn't help, since it doesn't actually write anything to standard out (when all is well) - it only serves to launch the other program.

For example, if you tried something like this:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t

... you would see the output in a new console, and nothing in in the calling window / process.

If you tried to redirect the output like this:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t > test.txt

... that wouldn't work either, since it would just be redirecting the output from start, which is nothing.

But this also doesn't work:

start /wait C:\Windows\system32\PING.EXE 8.8.8.8 -t ^> test.txt

... since there isn't anything to apply the escaped redirect to. That's why the question you linked suggests this:

start /wait cmd /c C:\Windows\system32\PING.EXE 8.8.8.8 -t ^> test.txt

This almost works, in that it starts the process, opens the window and runs the program, and captures the output in a file. But it does all of this from the new process, not in the calling process.

However, you want the text from the program to still show up on the new console window, as well as have live access to the same output in your script (in your case not to redirect it to a file, but presumably use it in some other way).

You can get close by starting the command in the new console with PowerShell, using Start-Process instead of cmd /c and using Tee-Object which is similar to the Linux tee command.

However, this only succeeds in writing the output to a file as well as to the console, all from the new console. You could of course monitor the file for changes from your Python script, but this would still only get you new data whenever Tee-Object flushes the file buffer to disk. I don't think there's a way for you to get this to work using normal console windows in Windows, simply due to the way those work, and the fact that you can't just redirect a stream from one process to another using console windows.

The solution here might be to write a Python script that runs in the new console window, both echoing the data to the console as well as processing it. You just launch this helper script from your original script and the effect is exactly what you need. You'd have to provide more details to explain why that wouldn't be a suitable solution in your case.

答案2

得分: 0

start 是一个Shell命令,而不是一个独立的程序。Popen 函数重定向运行程序的输出,而不是Shell命令的输出。

我们可以尝试创建一个批处理文件,启动你的程序并将其输出重定向到一个文件,然后使用 Popen 运行这个批处理文件。

让我们创建一个名为 start.bat 的批处理文件,其中包含以下内容:

start /wait program > output.txt

然后我们可以像这样使用 Popen 运行它:

import subprocess

p = subprocess.Popen(["start.bat"], shell=True)
英文:

start is a shell command, not a separate program. The Popen function redirects the output of the program it runs, not the output of shell commands.

We could try to create a batch file that starts your program and redirects its output to a file, and then run this batch file with Popen.

Lets do a start.bat batch file which contain:

start /wait program > output.txt

Then we can run it with Popen like that

import subprocess

p = subprocess.Popen(["start.bat"], shell=True)

huangapple
  • 本文由 发表于 2023年5月30日 07:42:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定