【问题标题】:Python capture output from wget?Python从wget捕获输出?
【发布时间】:2009-08-17 22:45:08
【问题描述】:

是否可以从 wget 和其他使用 curses 的命令行程序中捕获输出? 这是我现在拥有的:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=0)
for line in p.stdout:
    print "a"

这适用于具有简单输出的程序,但不适用于 wget 和其他使用 curses 的程序。

【问题讨论】:

  • 我不认为 wget 使用诅咒。它只是将消息打印到标准错误而不是标准输出。
  • 对于 wget 的情况,您可能需要拦截 stderr(请参阅 blog.doughellmann.com/2007/07/pymotw-subprocess.html 获取一些示例)对于拦截 curses 程序 - 我怀疑当您需要模拟时会很快变得乏味终端...
  • 糟糕,我认为要更新现有行必须使用 curses。
  • 在终端应用程序中打印进度条和微调器的常用方法是使用退格/擦掉字符。最好检查您的文件描述符是否已连接到终端(避免使用 ASCII 控制字符将常规文件弄乱)。但是,这不需要诅咒。事实上,Python termios 模块正是你所需要的。 (通常,即使没有 termios 模块,您也可以 sys.stdout.write(chr(0x08)) 在当前行的字符上退格)。

标签: python


【解决方案1】:

我不相信wget 正在使用诅咒。

通常当我想在脚本中使用wget 时,我会使用-O - 选项来强制其输出到stdout。我怀疑您正在尝试捕获运行控制台时通常在控制台上看到的文本,即 stderr

从命令行,在 Python 之外,只需运行如下命令:

wget -O - http://www.somesite.org/ > /tmp/wget.out 2> /tmp/wget.err

然后查看两个输出文件。如果您在控制台/终端上看到来自 wget 的任何输出,那么您运行的命令与我所看到的不同。

如果我怀疑你真的对 stderr 消息感兴趣,那么你有两个选择。

  • 将您的命令更改为添加 2>&1 并将 shell=True 添加到您的 Popen() 参数中
  • 或者(最好)将stderr=subprocess.PIPE 添加到您的Popen() 参数中

如果您不使用 stdout,前者很方便(假设您使用 wget 获取数据并将其写入文件)。在后一种情况下,您从 stderr 文件选项中读取数据以获取数据。

顺便说一句:如果您确实需要捕获 curses 数据...您可以尝试使用标准 pty 模块,但我不会不建议这样做。您最好从以下位置获取 pexpect 模块:

不要被年龄或版本号吓到,它适用于 Python 2.5 和 2.6 以及 2.4 和 2.3。

【讨论】:

  • 绝对符合预期,正如我在其他最近的答案中所推荐的那样——例如见stackoverflow.com/questions/1283061
  • 为什么要添加 shell=True?它一点也不方便——而且不必要地调用一个新的 shell 进程。
  • 我指出,对于 2>&1 排序的重定向,您要么必须执行 shell=True,要么必须执行自己的 os.fork(), os.dup2( ) 和 os.execve() 函数。
  • 您应该在 wget “完成”之前获得输出(即在该过程完成之前)。但是,您可能会看到一些缓冲效果。尝试在子进程列表上设置 bufsize=0。
  • @Jim Dennis:你错了。 subprocess.Popen 可以做2>&1 就好了,你不需要分叉任何东西,它适用于所有平台。只需使用subproces.Popen(cmd, stderr=subprocess.STDOUT)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
相关资源
最近更新 更多