【问题标题】:subprocess.Popen behavior after cx_freezecx_freeze 之后的 subprocess.Popen 行为
【发布时间】:2014-06-10 21:58:28
【问题描述】:

我有一些 python 代码使用 subprocess.Popen 打开控制台应用程序并从中获取 stdout/stderr。

从解释器启动工作正常且符合预期。

在使用带有--base-name Win32GUI 选项的 cx_freeze 后,Popen 现在会在控制台窗口中弹出,我无法捕获 stdout/stderr。如果我删除 --base-name Win32GUI 它会按预期工作,但我现在在 UI 后面有一个控制台。

这里是代码(我试过没有startupinfo和没有shell=False):

startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
subprocess.Popen(['exe', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)

我正在使用out, err = p.communicate() 来获取标准输出/标准错误

【问题讨论】:

  • 尝试给它stdin=subprocess.PIPE,即使你不想发送任何标准输入。 This page 建议您需要为其提供所有三个标准流的句柄。
  • 这似乎可行,但现在p.communicate() 正在为out 返回NoneType(错误仍然有效)。
  • 很奇怪。如果你给它stderr=subprocess.STDOUT 来合并它们会发生什么?
  • 您应该将Popen 调用放在try 语句中,并在引发异常时记录到文件中。
  • 如果您从命令提示符运行 exe,它可能继承了进程标准句柄的错误控制台缓冲区句柄。 Popen 将在无效句柄上调用 DuplicateHandle 时死掉。尝试以start my.exe 运行它。 start命令在进程CreationFlags中设置CREATE_NEW_CONSOLE,所以无效句柄不会被复制到GUI进程中。

标签: python python-3.x cx-freeze


【解决方案1】:

好的,我找到了解决方案。看起来因为它的 Windows GUI 应用程序标准输出句柄不存在,并且看起来子进程继承了该行为。所以一种解决方法是一个简单的解决方法,一个涉及win32api并为其创建管道的更复杂的解决方法(没有尝试这种方法)。

这是最终奏效的方法:

startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
stdout_file = tempfile.NamedTemporaryFile(mode='r+', delete=False)
process = subprocess.Popen(['exe', 'arg1', 'arg2'], stdin=subprocess.PIPE, stdout=stdout_file, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)
return_code = process.wait()
stdout_file.flush()
stdout_file.seek(0) # This is required to reset position to the start of the file
out = stdout_file.read()
stdout_file.close()

【讨论】:

  • 就我而言,我必须将encoding="UTF-16" 添加到 NamedTemporaryFile。这可以防止默认的“cp1252”编码......被stdout_file.read()误读(每个字符都用空格分隔)。 - 我的命令是:["wmic", "logicaldisk"]
  • 我遇到了同样的问题,这似乎对我有用
  • 这也适用于我,我使用了asyncio.create_subprocess_exec()
猜你喜欢
  • 2011-06-29
  • 2019-01-27
  • 1970-01-01
  • 2012-12-04
  • 2023-03-08
  • 2023-04-02
  • 2022-08-23
  • 2011-03-28
  • 1970-01-01
相关资源
最近更新 更多