如何判断通过subprocess.Popen打开的文件是否已经关闭?
我在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这样的库来实现,那就更好了。
1 个回答
0
你在找的东西是不是像这样:
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的资料,非阻塞和非僵尸进程以及如何杀死(或避免)使用子进程模块的僵尸进程,看起来在Linux中,调用communicate()是处理“僵尸”进程所需要的(我觉得在MacOS中也是如此)。
(查看StackOverflow的僵尸进程标签信息。)
这会生成类似于以下的输出:
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.