pidが有効なプロセスに対応しているかどうかを確認する方法はありますか?from以外の別のソースからpidを取得os.getpid()
しています。そのpidを持つプロセスがマシンに存在しないかどうかを確認する必要があります。
UnixとWindowsで利用できるようにする必要があります。また、PIDが使用されていないかどうかを確認しています。
pidが有効なプロセスに対応しているかどうかを確認する方法はありますか?from以外の別のソースからpidを取得os.getpid()
しています。そのpidを持つプロセスがマシンに存在しないかどうかを確認する必要があります。
UnixとWindowsで利用できるようにする必要があります。また、PIDが使用されていないかどうかを確認しています。
回答:
pidにシグナル0を送信すると、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
os.kill(pid, 0)
と同じos.kill(pid, signal.CTRL_C_EVENT)
です。これをサブプロセスで試したOSError
ところ、どこerrno==EINVAL
にあるのかがわかります。
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でこれを行うことはできません。外部libに依存することに問題がなければ、psutilを使用できます。
>>> import psutil
>>> psutil.pid_exists(2353)
True
プロセスへの「シグナル0」の送信に関する回答は、問題のプロセスがテストを実行しているユーザーによって所有されている場合にのみ機能します。それ以外の場合は、pidがシステムに存在していても、permissionsOSError
によりdueを取得します。
この制限を回避するために、/proc/<pid>
存在するかどうかを確認できます。
import os
def is_running(pid):
if os.path.isdir('/proc/{}'.format(pid)):
return True
return False
これは、明らかにLinuxベースのシステムにのみ適用されます。
PermissionError
pidが存在することを意味し、pidが存在ProcessLookupError
しない場合に取得します。
OSError
いずれかのエラー番号を見経由または複数の専門引く経由-拒否された権限によるものが他のものと区別することができますPermissionError
/ ProcessLookupError
から派生した例外をOSError
。さらに、プロセスが存在する場合にのみ権限エラーが発生します。したがって、あなたの例はLinuxや他のいくつかのUnicesで機能する代替方法にすぎませんが、適切にを呼び出すよりも完全ではありませんos.kill(pid, 0)
。
/proc
procfsのは、唯一のLinux上ではなく、さらにBSDやOSX上で終了します。
Python 3.3以降では、errno定数の代わりに例外名を使用できます。Posixバージョン:
import os
def pid_exists(pid):
if pid < 0: return False #NOTE: pid == 0 returns True
try:
os.kill(pid, 0)
except ProcessLookupError: # errno.ESRCH
return False # No such process
except PermissionError: # errno.EPERM
return True # Operation not permitted (i.e., process exists)
else:
return True # no error, we can send a signal to the process
実行中のプロセスとその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のソリューションを使用します。
ntrrgcをベースにして、Windowsのバージョンを強化して、プロセスの終了コードとアクセス許可を確認します。
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if os.name == 'posix':
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:
import ctypes
kernel32 = ctypes.windll.kernel32
HANDLE = ctypes.c_void_p
DWORD = ctypes.c_ulong
LPDWORD = ctypes.POINTER(DWORD)
class ExitCodeProcess(ctypes.Structure):
_fields_ = [ ('hProcess', HANDLE),
('lpExitCode', LPDWORD)]
SYNCHRONIZE = 0x100000
process = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
if not process:
return False
ec = ExitCodeProcess()
out = kernel32.GetExitCodeProcess(process, ctypes.byref(ec))
if not out:
err = kernel32.GetLastError()
if kernel32.GetLastError() == 5:
# Access is denied.
logging.warning("Access is denied to get pid info.")
kernel32.CloseHandle(process)
return False
elif bool(ec.lpExitCode):
# print ec.lpExitCode.contents
# There is an exist code, it quit
kernel32.CloseHandle(process)
return False
# No exit code, it's running.
kernel32.CloseHandle(process)
return True
GetExistCodeProcess
必要とPROCESS_QUERY_INFORMATION
し、PROCESS_QUERY_LIMITED_INFORMATION
アクセス権を。
GetExitCodeProcess
ハンドルとポインターを受け取ります。このサンプルでExitCodeProcess
は、ポインターのみである必要がある場合、2番目のパラメーターとして構造体を受け取ります。
GiampaoloRodolàの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
GetExitCodeProcess
アクセスできるかどうかを確認する必要があります。
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")
os.kill(pid, 0)
たり見たりする方法に比べて明らかに劣ってい/proc/{pid}
ます。1つのsyscallを実行してコードを子にフォークし、その子でシェルを実行します。シェルは余分なミニシェルスクリプトを解釈し、シェルはpgrepを実行する別の子をフォークし、最後にpgrepが反復し/proc
ます。あなたの答えは投稿された質問には答えません。OPは、PIDを指定してメソッドを要求しました。メソッドにはプロセス名が必要です。
私はあなたがそれを取得している目的のためにPIDを使用し、エラーを適切に処理すると思います。それ以外の場合、それは古典的なレースです(有効であることを確認したときにPIDが有効である可能性がありますが、後ですぐに消えます)。