使用(wx)python记录外部程序的输出

时间:2021-02-20 07:11:02

I'm writing a GUI for using the oracle exp/imp commands and starting sql-scripts through sqlplus. The subprocess class makes it easy to launch the commands, but I need some additional functionality. I want to get rid of the command prompt when using my wxPython GUI, but I still need a way to show the output of the exp/imp commands.

我正在编写一个GUI来使用oracle exp / imp命令并通过sqlplus启动sql-scripts。子流程类可以轻松启动命令,但我需要一些额外的功能。我想在使用我的wxPython GUI时摆脱命令提示符,但我仍然需要一种方法来显示exp / imp命令的输出。

I already tried these two methods:

我已经尝试过这两种方法:

command = "exp userid=user/pwd@nsn file=dump.dmp"

process = subprocess.Popen(command, stdout=subprocess.PIPE)
output = process.communicate()[0]

process = subprocess.Popen(command, stdout=subprocess.PIPE)
process.wait()
output = process.stdout.read()

Through one of these methods (forgot which one) I really got the output of exp/imp, but only after the command finishes, which is quite worthless to me, as I need a frequent update during these potentially long running operations. And sqlplus made even more problems, as sqlplus mostly wants some input when an error occurs. When this happens python waits for the process to finish but the user can't see the prompt, so you don't know how long to wait or what to do...

通过其中一种方法(忘记哪一种方法)我真的得到了exp / imp的输出,但只有在命令完成后才对我完全没用,因为我需要在这些可能长时间运行的操作中频繁更新。并且sqlplus带来了更多问题,因为sqlplus在发生错误时主要想要一些输入。当发生这种情况时,python等待进程完成但用户无法看到提示,因此您不知道等待多长时间或做什么...

What I'd like to have is a wrapper that outputs everything I can see on the standard commandline. I want to log this to a file and show it inside a wxPython control.

我想要的是一个包装器,它输出我在标准命令行上可以看到的所有内容。我想将其记录到一个文件中并在wxPython控件中显示它。

I also tried the code from this page: http://code.activestate.com/recipes/440554/ but this can't read the output either. The OutputWrapper from this answer doesn't work either: How can I capture all exceptions from a wxPython application?

我也试过这个页面的代码:http://code.activestate.com/recipes/440554/但是这也无法读取输出。此答案中的OutputWrapper也不起作用:如何从wxPython应用程序中捕获所有异常?

Any help would be appreciated!

任何帮助,将不胜感激!

EDIT:
The subprocesses don't seem to flush their output. I already tried it with .readline().
My Tool has to run on windows and unix, so pexpect is no solution if there's no windows version. And using cx_oracle would be extreme overkill as I would have to rebuild the whole functionality of exp, imp and sqlplus.

编辑:子进程似乎没有刷新他们的输出。我已经用.readline()尝试过了。我的工具必须在windows和unix上运行,所以如果没有Windows版本,那么pexpect就没有解决方案了。并且使用cx_oracle会极其矫枉过正,因为我必须重建exp,imp和sqlplus的整个功能。

4 个解决方案

#1


The solution is to use a list for your command

解决方案是使用命令列表

command = ["exp", "userid=user/pwd@nsn", "file=dump.dmp"]
process = subprocess.Popen(command, stdout=subprocess.PIPE)

then you read process.stdout in a line-by-line basis:

然后你逐行读取process.stdout:

line = process.stdout.readline()

that way you can update the GUI without waiting. IF the subprocess you are running (exp) flushes output. It is possible that the output is buffered, then you won't see anything until the output buffer is full. If that is the case then you are probably out of luck.

这样你就可以在不等待的情况下更新GUI。如果正在运行的子进程(exp)刷新输出。输出可能是缓冲的,然后在输出缓冲区已满之前您将看不到任何内容。如果是这种情况那么你可能运气不好。

#2


If you're on Linux, check out pexpect. It does exactly what you want.

如果您使用的是Linux,请查看pexpect。它完全符合你的要求。

If you need to work on Windows, maybe you should bite the bullet and use Python bindings to Oracle, such as cx_Oracle, instead of running CL stuff via subprocess.

如果您需要在Windows上工作,也许您应该咬紧牙关并使用Python绑定到Oracle,例如cx_Oracle,而不是通过子进程运行CL stuff。

#3


Are these solutions able to capture stderr as well? I see you have stdout= option above. How do you make sure to get stderr as well? Another question is is there a way to use import logging/import logging.handlers to capture command stdout/stderr. It would be interesting to be able to use the logger with its buildt in formatters/rotaters,etc.

这些解决方案是否也能捕获stderr?我看到你上面有stdout =选项。你如何确保获得stderr?另一个问题是有没有办法使用import logging / import logging.handlers来捕获命令stdout / stderr。能够将记录器与其格式化器/旋转器等中的构建一起使用将是有趣的。

#4


Try this:

import subprocess

command = "ping google.com"

process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
output = process.stdout
while 1:
    print output.readline(),

#1


The solution is to use a list for your command

解决方案是使用命令列表

command = ["exp", "userid=user/pwd@nsn", "file=dump.dmp"]
process = subprocess.Popen(command, stdout=subprocess.PIPE)

then you read process.stdout in a line-by-line basis:

然后你逐行读取process.stdout:

line = process.stdout.readline()

that way you can update the GUI without waiting. IF the subprocess you are running (exp) flushes output. It is possible that the output is buffered, then you won't see anything until the output buffer is full. If that is the case then you are probably out of luck.

这样你就可以在不等待的情况下更新GUI。如果正在运行的子进程(exp)刷新输出。输出可能是缓冲的,然后在输出缓冲区已满之前您将看不到任何内容。如果是这种情况那么你可能运气不好。

#2


If you're on Linux, check out pexpect. It does exactly what you want.

如果您使用的是Linux,请查看pexpect。它完全符合你的要求。

If you need to work on Windows, maybe you should bite the bullet and use Python bindings to Oracle, such as cx_Oracle, instead of running CL stuff via subprocess.

如果您需要在Windows上工作,也许您应该咬紧牙关并使用Python绑定到Oracle,例如cx_Oracle,而不是通过子进程运行CL stuff。

#3


Are these solutions able to capture stderr as well? I see you have stdout= option above. How do you make sure to get stderr as well? Another question is is there a way to use import logging/import logging.handlers to capture command stdout/stderr. It would be interesting to be able to use the logger with its buildt in formatters/rotaters,etc.

这些解决方案是否也能捕获stderr?我看到你上面有stdout =选项。你如何确保获得stderr?另一个问题是有没有办法使用import logging / import logging.handlers来捕获命令stdout / stderr。能够将记录器与其格式化器/旋转器等中的构建一起使用将是有趣的。

#4


Try this:

import subprocess

command = "ping google.com"

process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
output = process.stdout
while 1:
    print output.readline(),