Как узнать, был ли файл закрыт, если я открываю его с помощью subprocess.Popen?
Я открываю файлы, используя следующие команды в Python:
file = os.path.normpath(file_path)
phandler = subprocess.Popen(['open', '-W', file])
Я опрашиваю
is_opened = phandler.poll() == None
чтобы увидеть, был ли процесс завершен. Это работает, если процесс завершается с помощью cmd+Q. Тем не менее, это не работает, если я закрываю файл с помощью cmd+w. Какой надежный способ убедиться, что файл больше не открыт.
PS. От phandler я также могу получить идентификатор процесса, используя при необходимости phandler.pid.
Если нет другого способа сделать это, мне, возможно, придется использовать библиотеку, например watchdog, которая является оберткой над iNotify, но будет лучше, если я смогу добиться этого с помощью библиотеки, такой как psutils.
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: неблокирующий + несуществующий процесс и как убить (или избежать) процессы зомби с помощью модуля подпроцесса, кажется, что вызов Communication () необходим для обработки "зомби" процессов в Linux (а также, я думаю, в MacOS).
(См. Информацию о тегах Stackru для тега zombie-process.)
Это генерирует вывод, такой как:
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.