pid が有効なプロセスに対応しているかどうかを確認する方法はありますか? から以外の別のソースから pid を取得してos.getpid()
います。その pid を持つプロセスがマシンに存在しないかどうかを確認する必要があります。
Unix と Windows で利用できるようにする必要があります。PIDが使用されていないかどうかも確認しています。
シグナル 0 を pid に送信すると、pid が実行されていない場合は OSError 例外が発生し、それ以外の場合は何もしません。
import os
def check_pid(pid):
""" Check For the existence of a unix pid. """
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True
psutil
モジュールを見てください:
psutil (python システムおよびプロセス ユーティリティ) は、Python で実行中のプロセスとシステム使用率(CPU、メモリ、ディスク、ネットワーク)に関する情報を取得するためのクロスプラットフォーム ライブラリです。[...] 現在、Linux、Windows、OSX、FreeBSD、Sun Solaris 、 32 ビットと64ビットの両方のアーキテクチャをサポートしており、Python バージョンは2.6 から 3.4までです (Python 2.4 と 2.5 のユーザーは 2.1.3 バージョンを使用できます)。 . PyPy も機能することが知られています。
pid_exists()
指定されたpidを持つプロセスが存在するかどうかを確認するために使用できるという関数があります。
次に例を示します。
import psutil
pid = 12345
if psutil.pid_exists(pid):
print("a process with pid %d exists" % pid)
else:
print("a process with pid %d does not exist" % pid)
参考のため:
mluebke コードは 100% 正しいわけではありません。kill() は EPERM (アクセス拒否) を発生させることもできます。この場合、明らかにプロセスが存在することを意味します。これはうまくいくはずです:
(Jason R. Coombs のコメントに従って編集)
import errno
import os
def pid_exists(pid):
"""Check whether pid exists in the current process table.
UNIX only.
"""
if pid < 0:
return False
if pid == 0:
# According to "man 2 kill" PID 0 refers to every process
# in the process group of the calling process.
# On certain systems 0 is a valid PID but we have no way
# to know that in a portable fashion.
raise ValueError('invalid PID 0')
try:
os.kill(pid, 0)
except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
elif err.errno == errno.EPERM:
# EPERM clearly means there's a process to deny access to
return True
else:
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH)
raise
else:
return True
pywin32、ctypes、または C 拡張モジュールを使用しない限り、Windows でこれを行うことはできません。外部ライブラリに依存しても問題ない場合は、psutilを使用できます。
>>> import psutil
>>> psutil.pid_exists(2353)
True
問題のプロセスが test を実行しているユーザーによって所有されている場合にのみ、プロセスに「シグナル 0」を送信することを含む回答が機能します。そうしないと、pid がシステムに存在する場合でも、 OSError
due to permissionsが発生します。
この制限を回避するには、/proc/<pid>
存在するかどうかを確認できます。
import os
def is_running(pid):
if os.path.isdir('/proc/{}'.format(pid)):
return True
return False
これは明らかに Linux ベースのシステムにのみ適用されます。
実行中のプロセスとその ID の完全なリストを取得する Windows 固有の方法については、こちらを参照してください。それは次のようなものになります
from win32com.client import GetObject
def get_proclist():
WMI = GetObject('winmgmts:')
processes = WMI.InstancesOf('Win32_Process')
return [process.Properties_('ProcessID').Value for process in processes]
次に、このリストに対して取得した pid を確認できます。パフォーマンス コストについてはわかりません。pid の検証を頻繁に行う場合は、これを確認することをお勧めします。
*NIx の場合は、mluebke のソリューションを使用してください。
Giampaolo RodolàのPOSIXに対する答えとWindowsに対する私の答えを組み合わせると、次のようになりました。
import os
if os.name == 'posix':
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
import errno
if pid < 0:
return False
try:
os.kill(pid, 0)
except OSError as e:
return e.errno == errno.EPERM
else:
return True
else:
def pid_exists(pid):
import ctypes
kernel32 = ctypes.windll.kernel32
SYNCHRONIZE = 0x100000
process = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
if process != 0:
kernel32.CloseHandle(process)
return True
else:
return False
Windows では、次の方法で実行できます。
import ctypes
PROCESS_QUERY_INFROMATION = 0x1000
def checkPid(pid):
processHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_INFROMATION, 0,pid)
if processHandle == 0:
return False
else:
ctypes.windll.kernel32.CloseHandle(processHandle)
return True
まず、このコードでは、pid を指定してプロセスのハンドルを取得しようとしています。ハンドルが有効な場合は、プロセスのハンドルを閉じて True を返します。それ以外の場合は False を返します。OpenProcess のドキュメント: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx
これは Linux で機能します。たとえば、banshee が実行されているかどうかを確認したい場合... (banshee は音楽プレーヤーです)
import subprocess
def running_process(process):
"check if process is running. < process > is the name of the process."
proc = subprocess.Popen(["if pgrep " + process + " >/dev/null 2>&1; then echo 'True'; else echo 'False'; fi"], stdout=subprocess.PIPE, shell=True)
(Process_Existance, err) = proc.communicate()
return Process_Existance
# use the function
print running_process("banshee")
次のコードは、Linux と Windows の両方で機能し、外部モジュールに依存しません。
import os
import subprocess
import platform
import re
def pid_alive(pid:int):
""" Check For whether a pid is alive """
system = platform.uname().system
if re.search('Linux', system, re.IGNORECASE):
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True
elif re.search('Windows', system, re.IGNORECASE):
out = subprocess.check_output(["tasklist","/fi",f"PID eq {pid}"]).strip()
# b'INFO: No tasks are running which match the specified criteria.'
if re.search(b'No tasks', out, re.IGNORECASE):
return False
else:
return True
else:
raise RuntimeError(f"unsupported system={system}")
必要に応じて簡単に拡張できます
取得する目的に関係なく PID を使用し、エラーを適切に処理することをお勧めします。それ以外の場合は、古典的なレースです (PID が有効であることを確認すると有効である可能性がありますが、すぐに消えます)。