【问题标题】:Suppress subprocess console output in a python windowed (Tkinter) app在 python 窗口(Tkinter)应用程序中抑制子进程控制台输出
【发布时间】:2017-11-18 05:28:49
【问题描述】:

我正在尝试在使用

制作的 python 应用程序可执行文件中运行以下代码

pyinstaller -w -F script.py

def ffmpeg_command(sec):
    cmd1 = ['ffmpeg', '-f','gdigrab','-framerate',config.get('FFMPEG_Settings','Framerate'),'-i','desktop',gen_filename_from_timestamp_and_extension()]


    proc = subprocess.Popen(cmd1,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    duration = sec
    sleeptime = 0
    while proc.poll() is None and sleeptime < duration: 
        # Wait for the specific duration or for the process to finish
        time.sleep(1)
        sleeptime += 1

    proc.terminate()

当按下 Tkinter 按钮并从按钮单击处理程序中调用此代码时,将运行上述代码。

我的问题是,当我运行 exe 时,它​​不会运行 ffmpeg。 但是,如果我将命令设置为:

proc = subprocess.Popen(cmd1)

FFMPEG 确实运行,我得到了我想要的电影文件,但我可以看到 FFMPEG 的控制台窗口。所以我最终在我的电影中得到了控制台窗口。 (我负责在按钮单击处理程序中最小化 Tkinter 窗口)

我的问题是如何抑制控制台窗口并让 FFMPEG 以我想要的方式运行? 我查看了以下线程,但无法使其工作: How to hide output of subprocess in Python 2.7, Open a program with python minimized or hidden

谢谢

【问题讨论】:

  • 尝试将参数 shell=True 添加到 proc = subprocess.Popen(cmd1,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
  • @Stack - 感谢您的评论。我尝试将其修改为:proc = subprocess.Popen(cmd1,shell=True,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 但我仍然得到相同的结果:(
  • 如果您使用的是 Windows 7 或更早版本,您可能有一个错误的标准输入句柄。通过stdin=subprocess.DEVNULL 替换它。但是,将句柄设置为NUL 设备不会阻止控制台的分配或隐藏它。 shell=True 将通过STARTUPINFO 隐藏它,但如果可能的话最好避免使用外壳,并且根本不附加到控制台更简单。定义DETACHED_PROCESS = 8 并使用creationflags=DETACHED_PROCESS
  • @eryksun - 更改为proc = subprocess.Popen(cmd1,shell=True,stdin=subprocess.DEVNULL,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 让它像我想要的那样运行,但现在我无法终止 FFMPEG,它只是继续进行屏幕捕获。但是proc = subprocess.Popen(cmd1,stdin=subprocess.DEVNULL,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 会抑制输出,但会显示控制台窗口。您能否提供更多有关使用STARTUPINFO 隐藏控制台窗口的详细信息?
  • 你之前是如何通过关闭控制台窗口来终止它的?如果要终止进程,请使用proc = subprocess.Popen(cmd1,shell=True,stdin=subprocess.DEVNULL,st‌​dout=subprocess.DEVN‌​ULL, stderr=subprocess.DEVNULL, creationflags=DETACHED_PROCESS)。然后杀死它调用proc.terminate()

标签: python ffmpeg subprocess pyinstaller windows-console


【解决方案1】:

谢谢@Stack 和@eryksun! 我改成如下代码:

startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
cmd1 = ['ffmpeg', '-f','gdigrab','-framerate',config.get('FFMPEG_Settings','Framerate'),'-i','desktop',gen_filename_from_timestamp_and_extension()]  
proc = subprocess.Popen(cmd1,stdin=subprocess.DEVNULL,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,startupinfo=startupinfo)

实现了我想要的。 事实上,正如@eryksun 建议的那样,仅重定向输出并没有这样做,我还必须使用stdin=subprocess.DEVNULL 来抑制所有输出。

这仍然使控制台窗口可见,但是通过如上所述设置startupinfo,控制台窗口被隐藏了。 还验证了 FFMPEG 会在时间到期时消失。

感谢您的帮助!

【讨论】:

  • 你说你保留了shell=True,但是你没有在上面的代码中使用它,这是最好的,因为这个命令不需要shell。我仍然建议通过 DETACHED_PROCESS 创建标志告诉 Windows 根本不要创建控制台。
猜你喜欢
  • 2014-02-17
  • 2019-10-14
  • 2014-06-04
  • 1970-01-01
  • 2018-10-04
  • 2023-04-10
  • 2011-09-23
  • 2019-01-18
  • 2011-04-20
相关资源
最近更新 更多