यदि पायथन में दिए गए पिड के साथ एक प्रक्रिया मौजूद है, तो कैसे जांचें?


109

क्या यह देखने के लिए जांच करने का एक तरीका है कि क्या एक पीआईडी ​​एक वैध प्रक्रिया से मेल खाती है? मुझे इसके अलावा एक अलग स्रोत से एक पिड मिल रही है os.getpid()और मुझे यह देखने की ज़रूरत है कि क्या उस पिड के साथ एक प्रक्रिया मशीन पर मौजूद नहीं है।

मुझे यह यूनिक्स और विंडोज में उपलब्ध होना चाहिए। मैं यह देखने के लिए भी जांच कर रहा हूं कि क्या पीआईडी ​​उपयोग में नहीं है।


2
विंडोज एक गैर-मानक ओएस है। इस प्रकार की चीजें पोर्टेबल नहीं होती हैं। यह जानना कि आप दोनों नहीं हो सकते, आपकी प्राथमिकता क्या है? प्राथमिकता के रूप में एक को चुनें और प्रश्न को संपादित करें।
S.Lott

26
@ एस.लॉट विंडोज एक गैर-मानक ओएस है यह सबसे मूर्खतापूर्ण टिप्पणी में से एक है जिसे मैंने एसओ पर देखा है ...
पायोटर डोब्रोगोस्ट

2
@Piotr Dobrogost: क्या आप वह कोड प्रदान कर सकते हैं जो POSIX मानक यूनिक्स और गैर-POSIX मानक विंडोज को हैंडल करता है? यदि ऐसा है, तो कृपया एक उत्तर दें कि (ए) समस्या को हल करता है और (बी) यह स्पष्ट करता है कि विंडोज किसी तरह पोसिक्स मानक के अनुरूप है।
S.Lott

3
@PiotrDobrogost मुझे लगता है कि S.Lott की टिप्पणी बाजार विवरण की तुलना में कार्यान्वयन विवरण और एपीआई समर्थन के बारे में अधिक थी।
रॉय टिंकर

3
विंडोज निश्चित रूप से अन्य लोकप्रिय ओएस के साथ आम में कम है बाकी एक दूसरे के साथ करते हैं। (जो कोई भी वेब विकास करता है, वह इसी तरह कुख्यात Microsoft उत्पाद की तुलना कर सकता है।) लेकिन @ S.Lott के जवाब में: मैं शायद ही कभी विंडोज के लिए Python कोड लिखता हूं जो कि Linux, OSX, BSD, आदि पर भी काम करने वाला नहीं है, इसलिए मैं। ईमानदारी से 'प्राथमिकता के रूप में चुनें' सहायक सलाह नहीं है, खासकर क्योंकि पायथन अमूर्त मंच के मतभेदों को दूर करता है जितना कि व्यावहारिक।
माइकल शेपर

जवाबों:


162

यदि पिड नहीं चल रहा है, तो एक संकेत को 0 से एक पिड पर भेजना 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

3
लिनक्स और OSX में सुनिश्चित करने के लिए काम करता है, मैं विंडोज के लिए बात नहीं कर सकता। यह उस प्रक्रिया को नहीं मारता है जिस अर्थ में आप पूछ रहे हैं, यह संकेत 0 भेजता है, जो मूल रूप से "क्या आप चल रहे हैं?"।
mluebke

10
यह निश्चित रूप से विंडोज पर काम नहीं करता है, क्योंकि यूनिक्स जैसे सिग्नल जैसी कोई चीज नहीं है।
अलेक्जेंडर लेबेडेव

13
पूर्ण होने के लिए, आपको यह सुनिश्चित करने के लिए त्रुटि संख्या की जांच करनी चाहिए कि यह 3 है (अपवाद को पकड़ें और पहले आर्ग के लिए जांच करें)। यह महत्वपूर्ण है यदि लक्ष्य प्रक्रिया मौजूद है, लेकिन आपके पास सिग्नल भेजने की अनुमति नहीं है (जो भी कारण हो)।
haridsv

8
अब खिड़कियों द्वारा समर्थित है। docs.python.org/library/os.html?highlight=os.kill#os.kill
माइकल

15
os.kill विंडोज पर समर्थित है, लेकिन os.kill(pid, 0)यह उसी तरह है os.kill(pid, signal.CTRL_C_EVENT)जो प्रक्रिया को समाप्त कर सकता है (या विफल)। जब मैं एक उपप्रकार पर यह कोशिश करता हूं तो मुझे एक OSErrorजगह मिलती है errno==EINVAL
जेसन आर। कोम्स ने

76

psutilमॉड्यूल पर एक नजर :

psutil (पायथन सिस्टम और प्रोसेस यूटिलिटीज) पायथन में चल रही प्रक्रियाओं और सिस्टम उपयोग (सीपीयू, मेमोरी, डिस्क, नेटवर्क) के बारे में जानकारी प्राप्त करने के लिए एक क्रॉस-प्लेटफॉर्म लाइब्रेरी है । [...] यह वर्तमान में लिनक्स , विंडोज , ओएसएक्स , फ्रीबीएसडी और सन सोलारिस दोनों का समर्थन करता है , दोनों 32-बिट और 64-बिट आर्किटेक्चर, पाइथन संस्करणों के साथ 2.6 से 3.4 (पायथन 2.4 और 2.5 के उपयोगकर्ता 2.1.3 संस्करण का उपयोग कर सकते हैं) । PyPy को काम करने के लिए भी जाना जाता है।

इसमें एक फ़ंक्शन है जिसे pid_exists()आप यह जांचने के लिए उपयोग कर सकते हैं कि क्या दिए गए पिड के साथ एक प्रक्रिया मौजूद है।

यहाँ एक उदाहरण है:

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)

सन्दर्भ के लिए:



मेरे पास एक उदाहरण था जहां विंडोज पर pid_exists विश्वसनीय होना बंद कर दिया था। उपयोग में होने के कारण यह गलत रिपोर्टिंग थी। यह समय-समय पर अपडेट किए गए अपने psutil मॉड्यूल को रखने के लिए एक अनुस्मारक है - खासकर जब OS उन्नयन कर रहा हो।
डेमोन ब्रॉडी

62

mluebke कोड 100% सही नहीं है; किल () भी EPERM (पहुंच से वंचित) को बढ़ा सकता है जिस स्थिति में जाहिर है कि एक प्रक्रिया मौजूद है। यह काम करने वाला है:

(जेसन आर। कोम्बस की टिप्पणियों के अनुसार संपादित)

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 एक्सटेंशन मॉड्यूल का उपयोग नहीं करते हैं, आप विंडोज पर ऐसा नहीं कर सकते। यदि आप बाहरी देयता से निर्भर हैं तो आप psutil का उपयोग कर सकते हैं :

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

haridsv का सुझाव है कि परीक्षण e.errno होना चाहिए! = 3 शायद e.errno! = misno.ESRCH
जेसन आर।

क्यों? ESRCH का अर्थ है "ऐसी कोई प्रक्रिया नहीं"।
ग्याम्पोलो रोडोला

2
सही। चूंकि ESRCH का अर्थ है "ऐसी कोई प्रक्रिया नहीं", अशुद्ध! = ESRCH का अर्थ है "ऐसी कोई प्रक्रिया नहीं" या "प्रक्रिया मौजूद है", जो फ़ंक्शन के नाम के समान है। आपने विशेष रूप से EPERM का उल्लेख किया है, लेकिन अन्य संभावित त्रुटि कोड क्या हैं? त्रुटि कोड को एकल करना गलत लगता है जो कि चेक के आशय से संबंधित है, जबकि ESRCH निकट से संबंधित लगता है।
जेसन आर। कोम्ब्स

आप सही हे। मैंने उस कोड को संपादित किया, जो अब दर्शाता है कि आपने क्या सुझाव दिया है।
Giampaolo Rodolà

python3 os.kill () में फेंकता है ProcessLookupError
martinkunev

19

प्रक्रिया में 'सिग्नल 0' भेजने से जुड़े उत्तर तभी काम करेंगे जब प्रश्न में प्रक्रिया परीक्षण चलाने वाले उपयोगकर्ता के स्वामित्व में हो । अन्यथा आपको अनुमतियों केOSError कारण मिलेगा , भले ही सिस्टम में पिड मौजूद हो।

इस सीमा को बायपास करने के लिए आप देख सकते हैं कि क्या /proc/<pid>मौजूद है:

import os

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

यह केवल लिनक्स आधारित प्रणालियों पर लागू होता है, जाहिर है।


गलत। PermissionErrorइसका मतलब है किProcessLookupError अगर पीआईडी ​​मौजूद नहीं है , तो आप मौजूद हैं।
JFS

OSErrorसे इनकार अनुमति की वजह से अन्य लोगों से अलग किया जा सकता है - या तो errno को देख के माध्यम से या एक से अधिक विशेष को पकड़ने के माध्यम से PermissionError/ ProcessLookupErrorअपवाद है जहाँ से निकाले जाते हैं OSError। Futhermore, यदि प्रक्रिया मौजूद है, तो आपको केवल अनुमति त्रुटि मिलती है। इस प्रकार, आपका उदाहरण सिर्फ एक वैकल्पिक तरीका है जो लिनक्स और कुछ अन्य यूनियनों पर काम करता है लेकिन यह ठीक से कॉल करने से अधिक पूर्ण नहीं है os.kill(pid, 0)
मैकशलेपजिग

यह समाधान corss-platform नहीं है। ओपी चाहता है कि यह यूनिक्स और विंडोज पर उपलब्ध हो। /procProcfs केवल लिनक्स पर बाहर निकल जाता है, बीएसडी या OSX पर भी नहीं।
चार्ल्स

यह विधि विफल हो जाती है यदि / proc छुपाया गया है = 2, प्रक्रिया सूची में नहीं दिखाई देगी यदि यह किसी अन्य उपयोगकर्ता के स्वामित्व में है।
पर्किन्स

8

पायथन 3.3+ में, आप गलत स्थिरांक के बजाय अपवाद नामों का उपयोग कर सकते हैं। पॉज़िक्स संस्करण :

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

7

अपनी आईडी के साथ चलने वाली प्रक्रियाओं की पूरी सूची प्राप्त करने के लिए विंडोज़-विशिष्ट तरीके से यहां देखें । यह कुछ इस तरह होगा

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]

फिर आप इस सूची के विरुद्ध प्राप्त होने वाले सत्यापन को सत्यापित कर सकते हैं। मुझे प्रदर्शन लागत के बारे में कोई जानकारी नहीं है, इसलिए यदि आप अक्सर पीआईडी ​​सत्यापन करने जा रहे हैं तो आप इसे बेहतर तरीके से जांचेंगे।

* NIx के लिए, बस mluebke के घोल का उपयोग करें।


इसने मेरे लिए अच्छा काम किया। मैं एक प्रक्रिया के नाम की जाँच करना चाहता था, इसलिए "Name" के लिए "ProcessID" की अदला-बदली की और इसे True या False को वापस करने के लिए सूची में चेक में परिवर्तित किया।
जेम्स आरपी

6

Ntrrgc की बिल्डिंग पर मैंने विंडोज़ संस्करण को बनाया है ताकि यह प्रक्रिया निकास कोड और अनुमतियों के लिए जाँच करता है:

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

दरअसल, msdn.microsoft.com/en-us/library/windows/desktop/… के अनुसार , और अधिकारों का उपयोग करने की GetExistCodeProcessआवश्यकता है । PROCESS_QUERY_INFORMATIONPROCESS_QUERY_LIMITED_INFORMATION

ध्यान दें कि कोड गलत है। GetExitCodeProcessएक हैंडल और एक पॉइंटर प्राप्त करता है और इस नमूने में यह ExitCodeProcessदूसरे पैरामीटर के रूप में एक संरचना प्राप्त कर रहा है जब यह केवल एक पॉइंटर होना चाहिए।
Fabio Zadrozny

OpenProcess के बाद, GetLastError को देखना एक अच्छा विचार है। ERROR_ACCESS_DENIED का अर्थ है कि प्रक्रिया मौजूद है! इसका उपयोग करने का एक पूरा उदाहरण यहां दिया गया है: gist.github.com/ociule/8a48d2a6b15f49258a87b5f55be29250
ociule

4

संयोजन POSIX के लिए जैमपाओलो Rodolà के जवाब और विंडोज के लिए मेरा मैं यह मिल गया:

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

विंडोज़ 8.1 पर विंडोज़ संस्करण मेरे लिए काम नहीं करता है। आपको जांचना होगा GetExitCodeProcessऔर सुनिश्चित करना होगा कि आपकी पहुंच भी है।
स्पीडप्लेन

kernel32.OpenProcessकेवल उपयोग करना ही पर्याप्त नहीं है। जैसा कि यहां बताया गया है "यदि प्रक्रिया हाल ही में समाप्त हो गई, तो संभाल के लिए एक पिड अभी भी मौजूद हो सकता है।" यदि kernel32.OpenProcessगैर शून्य मान लौटाता है, तो हमें अभी भी kernel32.GetExitCodeProcessनिकास कोड की जांच करने की आवश्यकता है ।
मेव

2

विंडोज में, आप इसे इस तरह से कर सकते हैं:

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

सबसे पहले, इस कोड में आप दिए गए पीड के साथ प्रक्रिया के लिए एक हैंडल प्राप्त करने का प्रयास करते हैं। यदि हैंडल वैध है, तो प्रक्रिया के लिए हैंडल बंद करें और True लौटें; अन्यथा, आप गलत लौटाते हैं। OpenProcess के लिए दस्तावेज़: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx


2

यह लिनक्स के लिए काम करेगा, उदाहरण के लिए यदि आप जांचना चाहते हैं कि क्या बंशी चल रहा है ... (बंशी एक संगीत खिलाड़ी है)

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}। एक कोड को निष्पादित करने के बजाय, आपका कोड एक बच्चे को कांटा करता है, उस बच्चे में एक शेल निष्पादित करता है, शेल आपके सुपरफ़्लोर मिनी शेल-स्क्रिप्ट की व्याख्या करता है, शेल दूसरे बच्चे की तलाश करता है जो pgrep निष्पादित करता है और अंत में pgrep पर पुनरावृत्ति करता है /proc। आपका उत्तर पोस्ट किए गए प्रश्न का उत्तर नहीं देता है। ओपी ने पीआईडी ​​दी गई विधि के लिए कहा। आपकी विधि के लिए एक प्रक्रिया नाम की आवश्यकता है।
मैक्सक्लेपजिग

-2

मैं कहूंगा कि आप जो भी उद्देश्य प्राप्त कर रहे हैं उसके लिए पीआईडी ​​का उपयोग करें और त्रुटियों को इनायत से संभालें। अन्यथा, यह एक क्लासिक दौड़ है (पीआईडी ​​तब मान्य हो सकती है जब आप इसकी वैधता की जांच करते हैं, लेकिन बाद में तुरंत चले जाते हैं)


मुझे और अधिक विशिष्ट होना चाहिए था - मैं निवेश के लिए जाँच कर रहा हूँ। इसलिए, मैं मूल रूप से यह देखना चाहता हूं कि क्या एक पीआईडी ​​उपयोग में नहीं है।
इवान फॉसमार्क

1
लेकिन उस जवाब का आप क्या करेंगे? आपके द्वारा उस ज्ञान को प्राप्त करने के तुरंत बाद, कुछ उस पिड का उपयोग कर सकता है।
डेमियन_इन_यूनिबल २०'०

@Damien_The_Unbeliever - यह ठीक है कि अगर कुछ उस चीज का उपयोग कर रहा है जिसके बाद मैं उस ज्ञान को प्राप्त करता हूं, और मैं समझता हूं कि आप दौड़ की स्थिति के बारे में क्या कह रहे हैं, लेकिन मैं आपको आश्वस्त कर सकता हूं कि यह मेरी स्थिति के लिए लागू नहीं होता है।
इवान फॉसमार्क
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.