【问题标题】:How do I know if a file has been closed if I open it using subprocess.Popen?如果我使用 subprocess.Popen 打开文件,如何知道文件是否已关闭?
【发布时间】:2014-09-08 07:24:55
【问题描述】:

我在 python 中使用以下命令打开文件:

file = os.path.normpath(file_path)
phandler = subprocess.Popen(['open', '-W', file])

我正在投票

is_opened = phandler.poll() == None

查看进程是否已终止。如果使用 cmd+Q 终止进程,则它正在工作。但是,如果我使用 cmd+w 关闭文件,这将不起作用。确保文件不再打开的万无一失的方法是什么。

附言。如果需要,我还可以从 phandler 中使用 phandler.pid 获取进程 ID。

如果没有其他方法可以做到这一点,我可能不得不使用像 watchdog 这样的库,它是 iNotify 的包装器,但如果我可以使用像 psutils 这样的库来实现这一点,那就更好了。

【问题讨论】:

  • 从技术上讲,如果您使用的是 Mac OS X(正如 open 命令和在键盘快捷键中使用“cmd”所暗示的那样),watchdogFSEventskqueue,因为 inotify 是特定于 Linux 内核的。
  • 如果有 no 万无一失的方法来实现这一点,我不会感到惊讶...尤其是如果您想要一个跨平台的解决方案。
  • 您没有将file 传递给open 命令。 fileself.key 有什么关系?
  • 查看lsof 命令,该命令可用于列出特定进程打开的所有文件。然后,您可以检查您的文件是否在打开它的进程列表中。但是,您需要通过某种方式知道哪个应用程序实际打开了文件,因为open 本身不会打开文件;它只是将文件传递给适当的应用程序。
  • 注意vim 只打开文件足够长的时间来创建swp 文件,然后关闭它。您可以使用lsof 查看打开文件的所有进程。

标签: python subprocess psutil


【解决方案1】:

你正在寻找这样的东西:

from __future__ import print_function  # If in Python 2.x, import print function from Python 3.x

import os
import subprocess
import time

import psutil

def get_proc_status(pid):
    """Get the status of the process which has the specified process id."""

    proc_status = None
    try:
        proc_status = psutil.Process(pid).status()
    except psutil.NoSuchProcess as no_proc_exc:
        print(no_proc_exc)
    except psutil.ZombieProcess as zombie_proc_exc:  
        # For Python 3.0+ in Linux (and MacOS?).
        print(zombie_proc_exc)
    return proc_status

def open_file(app, file_path):
    """Open the specified file with the specified app, and wait for the file to be closed. """

    my_file = os.path.normpath(file_path)
    # phandler = subprocess.Popen(['open', '-W', my_file])
    # Must be for Macs. Doesn't work in Windows or Linux.
    phandler = subprocess.Popen([app, my_file])
    pid = phandler.pid

    pstatus = get_proc_status(pid)
    while pstatus is not None and pstatus != "zombie":
        # The allowed set of statuses might differ on your system.
        print("subprocess %s, current process status: %s." % (pid, pstatus))
        time.sleep(1)  # Wait 1 second.
        pstatus = get_proc_status(pid)
        # Get process status to check in 'while' clause at start of next loop iteration.

    if os.name == 'posix' and pstatus == "zombie":   # Handle zombie processes in Linux (and MacOS?).
        print("subprocess %s, near-final process status: %s." % (pid, pstatus))
        phandler.communicate()

    pstatus = get_proc_status(pid)
    print("subprocess %s, final process status: %s.\n" % (pid, pstatus))

open_file(r"Evince\bin\Evince.exe", "fuzzed_file.pdf")
open_file(r"Evince\bin\Evince.exe", "unfuzzed_file.pdf")

根据 Python:Non-Blocking + Non defunct processhow to kill (or avoid) zombie processes with subprocess module,似乎需要调用communicate() 来处理 Linux 中的“僵尸”进程(我认为在 MacOS 中也是如此)。

(参见 StackOverflow 的 Tag Info for zombie-process tag。)

这会生成如下输出:

subprocess 6844, current process status: running.
subprocess 6844, current process status: running.
subprocess 6844, current process status: running.
subprocess 6844, current process status: running.
psutil.NoSuchProcess no process found with pid 6844
psutil.NoSuchProcess no process found with pid 6844
subprocess 6844, final process status: None.

subprocess 5460, current process status: running.
subprocess 5460, current process status: running.
subprocess 5460, current process status: running.
subprocess 5460, current process status: running.
subprocess 5460, current process status: running.
subprocess 5460, current process status: running.
psutil.NoSuchProcess no process found with pid 5460
psutil.NoSuchProcess no process found with pid 5460
subprocess 5460, final process status: None.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多