2012-06-26 22 views
25

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

मान लें कि आप यह जांचना चाहते हैं कि wget या curl उपलब्ध हैं या नहीं। हम मान लेंगे कि वे पथ में होना चाहिए।

मल्टीप्लाफ्फ़्ट समाधान देखने के लिए सबसे अच्छा होगा लेकिन फिलहाल, लिनक्स पर्याप्त है।

संकेत:

  • आदेश चलाकर और बदले कोड के लिए जाँच हमेशा पर्याप्त रूप में कुछ उपकरणों लौट गैर 0 परिणाम भी जब आप --version कोशिश कर नहीं है। जब

भी आदेश के लिए जाँच

  • कुछ भी नहीं स्क्रीन पर दिखाई देना चाहिए, मैं मैं शायद which wget या which curl और जांच के लिए बाहर शेल की तरह is_tool(name)

  • +0

    के संभावित डुप्लिकेट [टेस्ट निष्पादन मौजूद रहने पर पायथन में?] (http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python) –

    उत्तर

    8
    import subprocess 
    import os 
    
    def is_tool(name): 
        try: 
         devnull = open(os.devnull) 
         subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate() 
        except OSError as e: 
         if e.errno == os.errno.ENOENT: 
          return False 
        return True 
    
    +2

    लौटाता है, यह उपप्रोसेसर अनिश्चित काल तक चल रहा है अगर यह या तो stdout या stderr के पाइप बफर भरता है। यदि आप प्रक्रिया * को अभी भी चलाने के लिए चाहते हैं * यह जांचने के लिए कि यह मौजूद है या नहीं, तो आपको ओपन 'os.devnull' का उपयोग करना चाहिए और इसे stdout और stderr के रूप में उपयोग करना चाहिए। –

    +0

    होने की संभावना नहीं है लेकिन आप सही हैं, धन्यवाद। – sorin

    +0

    पैरामीटर के बिना कॉल किए जाने पर कई टूल आउटपुट उपयोग की जानकारी, जो आसानी से पाइप बफर भर सकती है। मैं वैसे भी अपनी प्रारंभिक टिप्पणी के साथ गलत था - मुझे 'कॉमनेक्ट()' के लिए कॉल याद आया, जो कि कोड बॉक्स के दाएं हाशिए से बाहर था, और मैंने दाहिने ओर पर्याप्त स्क्रॉल नहीं किया था। विधि 'Popen.communicate()' किसी भी deadlocks से परहेज करने का ख्याल रखता है। –

    3

    , एक समाधान है कि अधिक व्यापक सराहना करेंगे यह परिणाम आपके द्वारा उपयोग किए जा रहे प्रोग्राम के नाम पर समाप्त होता है। यूनिक्स का जादू :)

    वास्तव में, आपको केवल which का रिटर्न कोड चेक करना है। तो ... हमारे भरोसेमंद subprocess मॉड्यूल का उपयोग कर:

    import 
    rc = subprocess.call(['which', 'wget']) 
    if rc == 0: 
        print 'wget installed!' 
    else: 
        print 'wget missing in path!' 
    

    ध्यान दें कि मैं cygwin के साथ खिड़कियों पर यह परीक्षण किया है ... आप यह पता लगाने की शुद्ध अजगर में which लागू करने के लिए कैसे करना चाहते हैं, मैं तुम्हें यहाँ की जाँच का सुझाव: http://pypi.python.org/pypi/pycoreutils (। ओह प्रिय - यह वे एक दोस्ताना कुहनी से हलका धक्का के लिए which समय नहीं दे रहे हों लगती है?)

    अद्यतन: Windows पर, आप एक समान प्रभाव के लिए where बजाय which उपयोग कर सकते हैं।

    +1

    क्या यह '' wget '' नामक प्रोग्राम चलाने की कोशिश नहीं करेगा, यानी फ़ाइल नाम में जगह? –

    +0

    @SvenMarnach, ठीक है! मुझे सिंटैक्स सब गलत मिला :(ओह प्रिय। –

    +1

    यह होना चाहिए: 'subprocess.call (['जो', 'wget'])' – nbubis

    31

    सबसे आसान तरीका है अगर यह मौजूद नहीं है वांछित मानकों के साथ कार्यक्रम चलाने के लिए प्रयास करें, और अपवाद को संभालने के लिए है:

    try: 
        subprocess.call(["wget", "your", "parameters", "here"]) 
    except OSError as e: 
        if e.errno == os.errno.ENOENT: 
         # handle file not found error. 
        else: 
         # Something else went wrong while trying to run `wget` 
         raise 
    

    यह अजगर में एक आम पैटर्न है: EAFP

    +0

    के लिए सही नहीं है। प्रोग्राम के लिए आप जानते हैं कि इसका उपयोग कैसे किया जाए, यह शायद इसके बारे में जाने का सबसे अच्छा तरीका है। आखिरकार: उम्मीद की उम्मीद अक्सर क्लीनर कोड की ओर ले जाती है ... –

    +1

    @DarenThomas: प्रोग्राम के लिए आप पता नहीं कैसे उपयोग करें, जानकारी है कि वे मौजूद हैं या नहीं, यह बहुत उपयोगी प्रतीत नहीं होता है। :) –

    +0

    मुझे आपका दृष्टिकोण पसंद है, लेकिन यह stdout और stderr को प्रदूषित करता है। इसके अलावा, यह एक समारोह नहीं है;) – sorin

    1
    import os 
    import subprocess 
    
    
    def is_tool(prog): 
        for dir in os.environ['PATH'].split(os.pathsep): 
         if os.path.exists(os.path.join(dir, prog)): 
          try: 
           subprocess.call([os.path.join(dir, prog)], 
               stdout=subprocess.PIPE, 
               stderr=subprocess.STDOUT) 
          except OSError, e: 
           return False 
          return True 
        return False 
    
    +0

    यह मंच-स्वतंत्र नहीं है: यदि आप वास्तव में ओएस कार्यक्षमता को दोहराना चाहते हैं, तो आपको कम से कम 'os.path.join() 'और' os.pathsep' का उपयोग करना चाहिए। –

    +0

    (मैंने 'os.pathsep' में भी संपादित किया - विंडोज़ पर, 'पथ' अर्धविराम-सीमांकित है।) –

    +0

    अच्छी पकड़, क्या मेरा संपादन आपके पथसे को ओवरराइट करता है? – ryanday

    14

    आप द्विआधारी के साथ की जरूरत के लिए एक उपप्रक्रिया कॉल इस्तेमाल कर सकते हैं:

    • "जो": * nix
    • "कहाँ": जीत 2003 और बाद में

    निष्पादन योग्य पथ प्राप्त करने के लिए (मान यह पर्यावरण पथ में है) (XP कोई एडऑन है)।

    import os 
    import platform 
    import subprocess 
    
    cmd = "where" if platform.system() == "Windows" else "which" 
    try: 
        subprocess.call([cmd, your_executable_to_check_here]) 
    except: 
        print "No executable" 
    

    या सिर्फ नेड बैटचेल्डर के wh का उपयोग करें।

    http://nedbatchelder.com/code/utilities/wh_py.html

    +0

    कॉल अपवाद नहीं फेंकता है जब प्रोग्राम मौजूद नहीं होता है, इसके बजाय कॉल गैर-शून्य – Photon

    0

    एक मामूली संशोधन @ SvenMarnach के कोड है कि मानक आउटपुट धारा को मुद्रण के मुद्दे को संबोधित करने के लिए: py स्क्रिप्ट, कि एक "जो" पार मंच कार्यान्वयन है। यदि आप subprocess.call() के बजाय subprocess.check_output() फ़ंक्शन का उपयोग करते हैं तो आप स्ट्रिंग को अपने कोड में मानक रूप से मुद्रित करने वाली स्ट्रिंग को नियंत्रित कर सकते हैं और अभी भी अपवाद और निकास स्थिति कोड पकड़ सकते हैं।

    आप टर्मिनल में मानक आउटपुट धारा को दबाने के लिए, स्ट्रिंग कि check_output से दिया जाता है एसटीडी प्रिंट आउट नहीं करना चाहते हैं:

    import subprocess 
    import os 
    try: 
        stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT) 
        # print(stdout_string) 
    except subprocess.CalledProcessError as cpe: 
        print(cpe.returncode) 
        print(cpe.output) 
    except OSError as e: 
        if e.errno == os.errno.ENOENT: 
         print(e) 
        else: 
         # Something else went wrong while trying to run `wget` 
         print(e) 
    

    गैर शून्य से बाहर निकलें स्थिति कोड और आउटपुट स्ट्रिंग उठाए गए हैं CalledProcessError में subprocess.CalledProcessError.returncode और subprocess.CalledProcessError.output के रूप में ताकि आप जो कुछ भी चाहें कर सकें।

    आप, टर्मिनल के लिए निष्पादन योग्य के मानक आउटपुट मुद्रित स्ट्रिंग है जो दिया जाता है प्रिंट करना चाहते हैं:

    import subprocess 
    import os 
    try: 
        stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT) 
        print(stdout_string) 
    except subprocess.CalledProcessError as cpe: 
        print(cpe.returncode) 
        print(cpe.output) 
    except OSError as e: 
        if e.errno == os.errno.ENOENT: 
         print(e) 
        else: 
         # Something else went wrong while trying to run `wget` 
         print(e) 
    

    print() स्ट्रिंग के लिए एक अतिरिक्त न्यू लाइन कहते हैं। आप (जैसा कि ऊपर) प्रिंट (के साथ दिखाया गया बयान और बाहर एसटीडी स्ट्रीम के बजाय एसटीडी अं धारा के मानक त्रुटि बारे में) है कि खत्म करने के लिए चाहते हैं, sys.stdout.write(string) और sys.stderr.write(string) बजाय प्रिंट() का उपयोग करें:

    import subprocess 
    import os 
    import sys 
    try: 
        stdout_string = subprocess.check_output(["bogus"], stderr=subprocess.STDOUT) 
        sys.stdout.write(stdout_string) 
    except subprocess.CalledProcessError as cpe: 
        sys.stderr.write(cpe.returncode) 
        sys.stderr.write(cpe.output) 
    except OSError as e: 
        if e.errno == os.errno.ENOENT: 
         sys.stderr.write(e.strerror) 
        else: 
         # Something else went wrong while trying to run `wget` 
         sys.stderr.write(e.strerror) 
    
    -1

    डेबियन आधारित सिस्टम के लिए:

    मैंने ऊपर से लिपियों का परीक्षण किया और वे वास्तव में अच्छे नहीं थे। वे कार्यक्रम चलाते हैं और यह परेशान है क्योंकि इसमें बहुत समय लगता है और आपको कार्यक्रम बंद करना होगा। मुझे योग्यता के साथ स्थापित संकुल प्राप्त करने का समाधान मिला, और फिर सूची पढ़ना।

    आप इंस्टॉल किए गए पैकेज ' Exemples के विभिन्न प्रकार प्राप्त करने के लिए आदेशों के विभिन्न प्रकार का उपयोग कर सकते हैं: https://askubuntu.com/questions/17823/how-to-list-all-installed-packages

    दो कि मैंने पाया सबसे अच्छा था:

    dpkg --get-selections   # big list 
    aptitude search '~i!~M' -F  # great list 
    

    आप उन्हें में चला सकते हैं परीक्षण करने के लिए टर्मिनल।


    अजगर समारोह:

    import os,sys 
    
    def check_for_program(program): 
    
        if not os.path.exists("/tmp/program_list"): 
         os.system("aptitude search '~i!~M' -F > /tmp/program_list") 
    
        with open('/tmp/program_list') as f: 
         for line in f: 
          if program in line: 
           return True 
        return False 
    
    +2

    यह केवल डेबियन आधारित सिस्टम पर काम करता है, और संकुल का नाम बदलते समय बुरी तरह विफल हो जाएगा, जो कभी-कभी होता है। –

    10

    मैं के लिए जाना चाहते हैं:

    import distutils.spawn 
    
    def is_tool(name): 
        return distutils.spawn.find_executable(name) is not None 
    
    +0

    'distutils.spawn' लिनक्स और मैक ओएस एक्स में अच्छी तरह से काम करता है। लेकिन बाद में, यदि आप 'ऐप' बनाते हैं, और आप निष्पादित करने के लिए डबल क्लिक करते हैं, तो 'distutils.spawn' हमेशा' कोई नहीं 'लौटाता है। – muammar

    23

    shutil.which

    मुझे एक विकल्प है कि अभी तक चर्चा नहीं की गई है की सिफारिश करते हैं: which का पाइथन कार्यान्वयन, विशेष रूप से shutil.which। इसे पायथन 3.3 में पेश किया गया था और यह लिनक्स, मैक और विंडोज का समर्थन करने वाले क्रॉस-प्लेटफार्म है। यह Python 2.x में whichcraft के माध्यम से भी उपलब्ध है। आप which के लिए कोड को केवल here से बाहर निकाल सकते हैं और इसे अपने प्रोग्राम में डालें।

    def is_tool(name): 
        """Check whether `name` is on PATH and marked as executable.""" 
    
        # from whichcraft import which 
        from shutil import which 
    
        return which(name) is not None 
    

    distutils.spawn.find_executable

    एक अन्य विकल्प है कि पहले से ही उल्लेख किया गया है distutils.spawn.find_executable है।

    Tries to find 'executable' in the directories listed in 'path'

    तो अगर आप ध्यान देना, आप ध्यान दें हूँ कि समारोह के नाम पर कुछ हद तक भ्रामक है:

    find_executable के docstring इस प्रकार है। which के विपरीत, find_executable वास्तव में सत्यापित नहीं करता है कि executable निष्पादन योग्य के रूप में चिह्नित किया गया है, केवल यह कि पथ पर है। तो यह पूरी तरह से संभव है (हालांकि असंभव) कि find_executable इंगित करता है कि एक प्रोग्राम उपलब्ध नहीं है जब यह नहीं है।

    उदाहरण के लिए, मान लें कि आपके पास फ़ाइल /usr/bin/wget है जो निष्पादन योग्य नहीं है। खोल से wget चलने से निम्नलिखित त्रुटि होगी: बैश:/usr/bin/wget: अनुमति से मना कर दी गई है। which('wget') is not None झूठी वापसी करेगा, फिर भी find_executable('wget') is not None सही होगा। आप शायद किसी भी फ़ंक्शन का उपयोग कर दूर हो सकते हैं, लेकिन यह find_executable के बारे में जागरूक होने के लिए कुछ है।

    def is_tool(name): 
        """Check whether `name` is on PATH.""" 
    
        from distutils.spawn import find_executable 
    
        return find_executable(name) is not None 
    
    +0

    'shutil.which()' के लिए दस्तावेज़ों से लिंक करें: https://docs.python.org/3/library/shutil.html#shutil.which –

    +0

    distutils.spawn.find_executable के लिए वोट दें! धन्यवाद दोस्त! – Barmaley

    2

    मैं @ Sorin का जवाब बदल देंगे इस प्रकार है, कारण यह कार्यक्रम का निरपेक्ष पथ गुजर बिना प्रोग्राम का नाम की जाँच करेगा है

    from subprocess import Popen, PIPE 
    
    def check_program_exists(name): 
        p = Popen(['/usr/bin/which', name], stdout=PIPE, stderr=PIPE) 
        p.communicate() 
        return p.returncode == 0 
    
    +0

    अफसोस की बात है, यह समाधान विंडोज प्लेटफ़ॉर्म के लिए काम नहीं करता है –

    संबंधित मुद्दे