كيفية التحقق مما إذا كان هناك عملية مع PID معينة في بيثون؟

StackOverflow https://stackoverflow.com/questions/568271

  •  05-09-2019
  •  | 
  •  

سؤال

هل هناك طريقة للتحقق لمعرفة ما إذا كانت PID تتوافق مع عملية صالحة؟ أحصل على PID من مصدر مختلف آخر غير من os.getpid() وأحتاج إلى التحقق لمعرفة ما إذا كانت العملية مع تلك PID غير موجودة على الجهاز.

أحتاج إلى أن تكون متاحة في UNIX والنوافذ. أنا أيضا التحقق لمعرفة ما إذا كانت PID ليست قيد الاستخدام.

هل كانت مفيدة؟

المحلول

سوف يرفع إرسال إشارة 0 إلى PID استثناء OSERROR إذا كانت PID لا تعمل، ولا تفعل شيئا خلاف ذلك.

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 وأدوات التحكم في العملية) هي مكتبة عبر منصة لاسترداد المعلومات ادارة العمليات و استخدام النظام (وحدة المعالجة المركزية والذاكرة والأقراص والشبكة) في بيثون. [...] يدعم حاليا لينكس, شبابيك, أوسكس, freebsd. و الشمس سولاريس, ، على حد سواء 32 بت و 64 بت البنية، مع إصدارات بيثون من 2.6 إلى 3.4. (مستخدمي Python 2.4 و 2.5 قد يستخدمون 2.1.3 الإصدار). من المعروف أيضا أن العمل.

لديها وظيفة تسمى 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
import sys

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

لا يمكنك القيام بذلك على Windows إلا إذا كنت تستخدم PYWIN32 أو CTTYPES أو وحدة تمديد C. إذا كنت موافق مع اعتمادا من ليب خارجي يمكنك استخدامه PSUTIL.:

>>> import psutil
>>> psutil.pid_exists(2353)
True

الإجابات التي تنطوي على إرسال "إشارة 0" للعملية ستعمل فقط إذا كانت العملية المعنية مملوكة للمستخدم قيد التشغيل. وبعد وإلا سوف تحصل على OSError بسبب الأذونات, ، حتى لو وجدت PID في النظام.

من أجل تجاوز هذا القيد، يمكنك التحقق مما إذا /proc/<pid> موجود:

import os

def is_running(pid):
    if os.path.isdir('/proc/{}'.format(pid)):
        return True
    return False

هذا ينطبق على الأنظمة القائمة على نظام Linux فقط، من الواضح.

نظرة هنا بالنسبة إلى طريقة محددة بين 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.

في Python 3.3+، يمكنك استخدام أسماء الاستثناءات بدلا من ثوابت Errno. نسخة بوسيكس:

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

بناء على 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

الجمع بين جامباوولو رودولا إجابة بوسيكس و الألغام لنظام التشغيل 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. إذا كان المقبض صالحا، فقم بإغلاق مقبض العملية وإرجاعه صحيحا؛ خلاف ذلك، فإنك تعود خطأ. وثائق OpenProcess: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320٪28V=V.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")

أود أن أقول استخدام PID لأي غرض يمكنك الحصول عليه والتعامل مع الأخطاء بأمان. خلاف ذلك، إنه سباق كلاسيكي (قد تكون PID صالحة عند التحقق من أنها صالحة، ولكن ابتعد عن لحظة لاحقا)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top