【问题标题】:Monitor sub process created from a shell command in windows监视从 Windows 中的 shell 命令创建的子进程
【发布时间】:2017-06-09 21:34:28
【问题描述】:

我正在使用subprocess.Popen打开一个程序

import subprocess

prog = subprocess.Popen(['myprog', args], shell=True)

我想监视进程“myprog”并等待它终止,然后我的代码继续。

我面临的问题是prog.pid 是shell 的PID 而不是'myprog',我不知道如何获得'myprog' 的PID。我尝试使用psutil查找prog.pid的子进程:

parent = psutil.Process(prog.pid)
children = parent.children(recursive=True)

但返回一个空列表。

不幸的是,没有外壳我无法启动“myprog”。当我使用shell=False 运行命令时,我收到以下错误消息: FileNotFoundError: [WinError 2] The system cannot find the file specified

我在网上搜索了很多,但所有有希望的线索都是针对非 Windows 用户的。

【问题讨论】:

  • 你确定你不能在没有shell的情况下制作你的程序吗?你能在你的问题中解释为什么吗?也许使用实际的命令行。因为这是可以修复的。
  • 我正在尝试使用命令atom path\to\file\to\open打开Atom
  • 你能输入where atom吗?我们要去这里的某个地方。
  • 是的,我可以。输出在 C:\Users\Username\AppData\Local\atom\bin 有 2 个文件 atomatom.cmd

标签: python windows shell subprocess


【解决方案1】:

您的atom 命令可能是一个启动可执行文件的.cmd 文件,这解释了shell=True 的必要性

你不会去在 python 中重新编码 .bat 文件的扩展,但是你也不需要可执行的 PID。

如果可执行文件结束,批处理文件结束,所以忘记监控prog.pid,只需使用poll 监控prog(当然在同一个python 脚本中)。

poll 方法允许检查进程是否已结束(如果已结束,则返回退出代码,如果尚未结束,则返回 None),这是非阻塞的,因此您可以这样做随时随地:

if prog.poll() is not None:
    # process has ended
    print("ended")

让我们提醒阻塞等待这样做:

return_code = prog.wait()

但在您的情况下,atom.cmd 命令似乎在后台启动进程,因此如果没有 PID,就无法进行监控。

在这种情况下,一种解决方法是制作atom.cmd 的副本,删除start 前缀以在前台运行可执行文件并改为运行副本。

(或者由于cmd 调用了另一个atom.cmd 文件,请从atom.cmd 原始目录中找到文件app-1.13.0\resources\cli\atom.cmd 并删除那里的start 前缀)

【讨论】:

  • 我曾尝试使用 prog.pollprog.wait(),但它很快就终止了,这让我相信我正在监视 shell 而不是“myprog”
  • 我在文本编辑器中打开了 atom.cmd 文件,内容如下:line 1@echo off line 2"%~dp0\..\app-1.13.0\resources\cli\atom.cmd" %*。我没有看到开始前缀
  • 并不是说它改变了这个问题,而是Popen 实际上不需要shell=True 来运行 .cmd 或 .bat 文件。但是,您必须使用带有扩展名的全名,因为“.EXE”是底层CreateProcess 调用尝试附加的唯一扩展名。
  • @EDWhyte 查看我的编辑。尝试删除另一个 atom.cmd 文件中的 start
猜你喜欢
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
相关资源
最近更新 更多