सवाल पायथन में बाहरी कमांड को कॉल करना


मैं एक पाइथन स्क्रिप्ट के भीतर से बाहरी आदेश (जैसे कि मैं इसे यूनिक्स शैल या विंडोज कमांड प्रॉम्प्ट पर टाइप कर सकता हूं) कैसे कॉल कर सकता हूं?


3635
2017-09-18 01:35


मूल




जवाब:


की ओर देखने के लिए उपप्रोसेसर मॉड्यूल मानक पुस्तकालय में:

from subprocess import call
call(["ls", "-l"])

का लाभ उपप्रक्रिया बनाम प्रणाली यह है कि यह अधिक लचीला है (आप stdout, stderr, "असली" स्थिति कोड, बेहतर त्रुटि हैंडलिंग, आदि प्राप्त कर सकते हैं ...)।

आधिकारिक दस्तावेज सिफारिश करता है उपप्रक्रिया वैकल्पिक os.system () पर मॉड्यूल:

उपप्रक्रिया मॉड्यूल नई प्रक्रियाओं को बढ़ाने और उनके परिणामों को पुनर्प्राप्त करने के लिए और अधिक शक्तिशाली सुविधाएं प्रदान करता है; उस मॉड्यूल का उपयोग इस समारोह का उपयोग करने के लिए बेहतर है [os.system()]।

"Subprocess मॉड्यूल के साथ पुराने कार्यों को बदलना"खंड में उपप्रक्रिया दस्तावेज में कुछ उपयोगी व्यंजन हो सकते हैं।

पर आधिकारिक दस्तावेज उपप्रक्रिया मॉड्यूल:


3504
2017-09-18 01:39



परिवर्तनीय प्रतिस्थापन का उपयोग करने का कोई तरीका है? आईई मैंने करने की कोशिश की echo $PATH का उपयोग करके call(["echo", "$PATH"]), लेकिन यह सिर्फ शाब्दिक स्ट्रिंग गूंज $PATH किसी भी प्रतिस्थापन करने के बजाय। मुझे पता है कि मैं पाथ पर्यावरण परिवर्तनीय प्राप्त कर सकता हूं, लेकिन मुझे आश्चर्य है कि कमांड का व्यवहार करने का एक आसान तरीका है जैसे कि मैंने इसे बाश में निष्पादित किया था। - Kevin Wheeler
@ केविन व्हाइलर आपको उपयोग करना होगा shell=True इसके लिए काम करने के लिए। - SethMMorton
@ केविन व्हाइलर आपको उपयोग नहीं करना चाहिए shell=True, इस उद्देश्य के लिए पाइथन के साथ आता है os.path.expandvars। आपके मामले में आप लिख सकते हैं: os.path.expandvars("$PATH")। @SethMMorton कृपया अपनी टिप्पणी पर पुनर्विचार करें -> शैल = सही का उपयोग क्यों न करें - Murmel
पायथन 3.5 के अनुसार, यह सुझाव दिया जाता है कि आप इसका उपयोग करते हैं subprocess.run के बजाय subprocess.call। docs.python.org/3/library/subprocess.html - Hannes Karppila
उदाहरण कॉल करता है ls -l लेकिन इसके आउटपुट तक पहुंच नहीं देता है (stdout उपलब्ध नहीं है)। मुझे यह भ्रमित लगता है - आप बिना किसी स्टडआउट के कमांड का उपयोग कर सकते हैं, जैसे कि touch। - florisla


बाहरी कार्यक्रमों और प्रत्येक के फायदे और नुकसान कहने के तरीकों का सारांश यहां दिया गया है:

  1. os.system("some_command with args") आपके सिस्टम के खोल में कमांड और तर्क पास करता है। यह अच्छा है क्योंकि आप वास्तव में इस तरह से एक से अधिक कमांड चला सकते हैं और पाइप और इनपुट / आउटपुट रीडायरेक्शन सेट कर सकते हैं। उदाहरण के लिए:

    os.system("some_command < input_file | another_command > output_file")  
    

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

  2. stream = os.popen("some_command with args") वही काम करेंगे os.system सिवाय इसके कि यह आपको एक फ़ाइल जैसी वस्तु देता है जिसे आप उस प्रक्रिया के लिए मानक इनपुट / आउटपुट तक पहुंचने के लिए उपयोग कर सकते हैं। पॉपन के 3 अन्य प्रकार हैं जो सभी I / o को थोड़ा अलग तरीके से संभालते हैं। यदि आप सब कुछ एक स्ट्रिंग के रूप में पास करते हैं, तो आपका आदेश खोल को पास कर दिया जाता है; यदि आप उन्हें एक सूची के रूप में पास करते हैं तो आपको कुछ भी बचने की चिंता करने की आवश्यकता नहीं है। देख दस्तावेज़ीकरण

  3. Popen की कक्षा subprocess मॉड्यूल। यह एक प्रतिस्थापन के रूप में इरादा है os.popen लेकिन इतना व्यापक होने के कारण थोड़ा और जटिल होने का नकारात्मक पक्ष है। उदाहरण के लिए, आप कहेंगे:

    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
    

    के बजाय:

    print os.popen("echo Hello World").read()
    

    लेकिन 4 अलग-अलग पॉपन कार्यों के बजाय एक एकीकृत वर्ग में सभी विकल्पों को रखना अच्छा लगता है। देख दस्तावेज़ीकरण

  4. call से काम subprocess मॉड्यूल। यह मूल रूप से बस की तरह है Popen कक्षा और सभी समान तर्क लेता है, लेकिन यह आदेश तब तक प्रतीक्षा करता है जब तक आदेश पूरा नहीं होता है और आपको रिटर्न कोड देता है। उदाहरण के लिए:

    return_code = subprocess.call("echo Hello World", shell=True)  
    

    देख दस्तावेज़ीकरण

  5. यदि आप पाइथन 3.5 या बाद में हैं, तो आप नए का उपयोग कर सकते हैं subprocess.run फ़ंक्शन, जो उपरोक्त की तरह बहुत अधिक है लेकिन इससे भी अधिक लचीला है और एक देता है CompletedProcess आदेश जब आदेश निष्पादित खत्म होता है।

  6. ओएस मॉड्यूल में आपके पास एक सी प्रोग्राम में सभी कांटा / निष्पादन / स्पॉन फ़ंक्शन भी होते हैं, लेकिन मैं उन्हें सीधे उपयोग करने की अनुशंसा नहीं करता हूं।

subprocess मॉड्यूल शायद आपके द्वारा उपयोग किया जाना चाहिए।

अंत में कृपया ध्यान रखें कि सभी विधियों के लिए जहां आप शेल द्वारा अंतिम स्ट्रिंग को स्ट्रिंग के रूप में निष्पादित करने के लिए पास करते हैं और आप इसे से बचने के लिए ज़िम्मेदार हैं। गंभीर सुरक्षा प्रभाव हैं यदि आपके द्वारा पारित स्ट्रिंग का कोई भी हिस्सा पूरी तरह से भरोसा नहीं किया जा सकता है। उदाहरण के लिए, यदि कोई उपयोगकर्ता स्ट्रिंग के कुछ / किसी भी भाग में प्रवेश कर रहा है। यदि आप अनिश्चित हैं, तो केवल इन तरीकों का उपयोग स्थिरांक के साथ करें। आपको प्रभावों का संकेत देने के लिए इस कोड पर विचार करें:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

और कल्पना करें कि उपयोगकर्ता प्रवेश करता है "मेरी माँ ने मुझे प्यार नहीं किया और & rm -rf /"।


2469
2017-09-18 13:11



अच्छा जवाब / स्पष्टीकरण। इस आलेख में वर्णित पाइथन के आदर्श वाक्य को न्यायसंगत कैसे उत्तर दिया जा रहा है? fastcompany.com/3026446/...  "स्टाइलिस्टिक रूप से, पर्ल और पायथन के अलग-अलग दर्शन होते हैं। पर्ल का सबसे अच्छा ज्ञात मोटो" यह करने के लिए एक और तरीका है "। पाइथन को ऐसा करने का एक स्पष्ट तरीका है" ऐसा लगता है कि यह दूसरा तरीका होना चाहिए! पर्ल में मुझे बैक-टिक का उपयोग करके कमांड निष्पादित करने के केवल दो तरीके पता हैं open। - Jean
यदि पाइथन 3.5+ का उपयोग करते हैं, तो उपयोग करें subprocess.run()। docs.python.org/3.5/library/subprocess.html#subprocess.run - phoenix
आम तौर पर यह जानने की ज़रूरत है कि बाल प्रक्रिया के एसटीडीओयूटी और एसटीडीईआरआर के साथ क्या किया जाता है, क्योंकि अगर उन्हें कुछ (काफी आम) स्थितियों के तहत अनदेखा किया जाता है, तो आखिर में बाल प्रक्रिया एसटीडीओयूटी (एसटीडीईआरआर) को लिखने के लिए सिस्टम कॉल जारी करेगी?) जो ओएस द्वारा प्रक्रिया के लिए प्रदान किए गए आउटपुट बफर से अधिक होगा, और ओएस उस बफर से कुछ प्रक्रिया पढ़ने तक इसे अवरुद्ध कर देगा। तो, वर्तमान में अनुशंसित तरीकों के साथ, subprocess.run(..), वास्तव में क्या करता है "यह डिफ़ॉल्ट रूप से stdout या stderr पर कब्जा नहीं करता है।" मतलब? व्हाट अबाउट subprocess.check_output(..) और एसटीडीईआरआर? - Evgeni Sergeev
आपके द्वारा अनुशंसित आदेशों में से कौन सी मेरी स्क्रिप्ट को अवरुद्ध करता है? यानी अगर मैं एक में कई कमांड चलाने के लिए चाहता हूँ for लूप मैं अपनी पायथन लिपि को अवरुद्ध किए बिना इसे कैसे कर सकता हूं? मुझे कमांड के आउटपुट की परवाह नहीं है, मैं बस उनमें से बहुत से भागना चाहता हूं। - Charlie Parker
@ फीनिक्स मैं असहमत हूं। Python3 में os.system का उपयोग करने से आपको कुछ भी नहीं रोक रहा है docs.python.org/3/library/os.html#os.system - Qback


मैं आमतौर पर उपयोग करता हूं:

import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

आप जो भी चाहते हैं उसे करने के लिए स्वतंत्र हैं stdout पाइप में डेटा। वास्तव में, आप बस उन पैरामीटर को छोड़ सकते हैं (stdout= तथा stderr=) और यह व्यवहार करेगा os.system()


257
2017-09-18 18:20



.readlines() पढ़ता सब लाइनें एक बार यानी, जब तक उपप्रोसेस निकलता है तब तक यह अवरुद्ध हो जाता है (पाइप के अंत को बंद कर देता है)। वास्तविक समय में पढ़ने के लिए (यदि कोई बफरिंग समस्या नहीं है) तो आप यह कर सकते हैं: for line in iter(p.stdout.readline, ''): print line, - jfs
क्या आप "क्या कोई बफरिंग समस्या नहीं है" से आपका क्या मतलब है? अगर प्रक्रिया निश्चित रूप से ब्लॉक हो जाती है, तो उपप्रोसेसर कॉल भी ब्लॉक करता है। मेरे मूल उदाहरण के साथ भी ऐसा ही हो सकता है। बफरिंग के संबंध में और क्या हो सकता है? - EmmEff
बाल प्रक्रिया लाइन-बफरिंग के बजाए गैर-इंटरैक्टिव मोड में ब्लॉक-बफरिंग का उपयोग कर सकती है p.stdout.readline()(नोट: नहीं s अंत में) जब तक बच्चा अपना बफर भरता है तब तक कोई डेटा नहीं दिखाई देगा। अगर बच्चा ज्यादा डेटा नहीं देता है तो आउटपुट वास्तविक समय में नहीं होगा। में दूसरा कारण देखें प्रश्न: क्यों न सिर्फ एक पाइप (popen ()) का उपयोग करें?। कुछ कामकाज प्रदान किए जाते हैं इस जवाब में (pexpect, pty, stdbuf) - jfs
बफरिंग समस्या केवल तभी मायने रखती है जब आप वास्तविक समय में आउटपुट चाहते हैं और आपके कोड पर लागू नहीं होते हैं जो कुछ भी प्रिंट नहीं करता है सब डेटा प्राप्त होता है - jfs


कॉलिंग से बच्चे की प्रक्रिया को अलग करने पर कुछ संकेत (पृष्ठभूमि में बाल प्रक्रिया शुरू करना)।

मान लीजिए कि आप एक सीजीआई-स्क्रिप्ट से एक लंबा काम शुरू करना चाहते हैं, यह कि बाल प्रक्रिया सीजीआई-स्क्रिप्ट निष्पादन प्रक्रिया से अधिक समय तक जीवित रहनी चाहिए।

उपप्रोसेसर मॉड्यूल दस्तावेज़ों का शास्त्रीय उदाहरण है:

import subprocess
import sys

# some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess

# some more code here

यहां विचार यह है कि जब तक longtask.py समाप्त नहीं हो जाता है तब तक आप 'कॉल सबप्रोसेस' लाइन में प्रतीक्षा नहीं करना चाहते हैं। लेकिन यह स्पष्ट नहीं है कि उदाहरण के बाद 'यहां कुछ और कोड' लाइन के बाद क्या होता है।

मेरा लक्ष्य मंच फ्रीब्स था, लेकिन विकास खिड़कियों पर था, इसलिए मुझे पहले विंडोज़ पर समस्या का सामना करना पड़ा।

विंडोज़ (एक्सपी जीतें) पर, पैरेंट प्रक्रिया तब तक खत्म नहीं होगी जब तक कि longtask.py ने अपना काम पूरा नहीं कर लिया हो। सीजीआई-स्क्रिप्ट में आप यही नहीं चाहते हैं। समस्या पाइथन के लिए विशिष्ट नहीं है, PHP समुदाय में समस्याएं समान हैं।

समाधान DETACHED_PROCESS को पास करना है प्रक्रिया निर्माण झंडा जीत एपीआई में अंतर्निहित CreateProcess फ़ंक्शन के लिए। यदि आपने pywin32 स्थापित किया है तो आप win32process मॉड्यूल से ध्वज आयात कर सकते हैं, अन्यथा आपको इसे स्वयं परिभाषित करना चाहिए:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/ * यूपीडी 2015.10.27 नोट्स के नीचे एक टिप्पणी में @eryksun, कि अर्थात् सही ध्वज CREATE_NEW_CONSOLE (0x00000010) * /

Freebsd पर हमें एक और समस्या है: जब माता-पिता की प्रक्रिया समाप्त हो जाती है, तो यह बाल प्रक्रियाओं को भी समाप्त करती है। और यही वह नहीं है जो आप सीजीआई-स्क्रिप्ट में चाहते हैं। कुछ प्रयोगों से पता चला कि समस्या sys.stdout साझा करने में लग रही थी। और कामकाजी समाधान निम्नलिखित था:

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

मैंने अन्य प्लेटफार्मों पर कोड की जांच नहीं की है और freebsd पर व्यवहार के कारणों को नहीं जानते हैं। अगर कोई जानता है, तो कृपया अपने विचार साझा करें। पाइथन में पृष्ठभूमि प्रक्रिया शुरू करने पर गुगल करने से अभी तक कोई प्रकाश नहीं निकलता है।


158
2018-02-12 10:15



मैंने pydev + ग्रहण में py2exe ऐप्स के विकास के साथ एक संभावित "quirk" देखा। मैं यह बताने में सक्षम था कि मुख्य लिपि को अलग नहीं किया गया था क्योंकि ग्रहण की आउटपुट विंडो समाप्त नहीं हुई थी; भले ही स्क्रिप्ट पूरा होने के लिए निष्पादित हो, फिर भी यह रिटर्न की प्रतीक्षा कर रहा है। लेकिन, जब मैंने एक py2exe निष्पादन योग्य को संकलित करने का प्रयास किया, तो अपेक्षित व्यवहार होता है (प्रक्रियाओं को पृथक के रूप में चलाता है, फिर छोड़ देता है)। मुझे यकीन नहीं है, लेकिन निष्पादन योग्य नाम अब प्रक्रिया सूची में नहीं है। यह सभी दृष्टिकोणों के लिए काम करता है (ओएससिस्टम ("स्टार्ट *"), os.P_DETACH, सबप्रॉक्स, आदि के साथ os.spawnl) - maranas
विंडोज गॉचा: भले ही मैंने DETACHED_PROCESS के साथ प्रक्रिया उत्पन्न की, जब मैंने अपने पायथन डिमन को मार दिया, तब तक खोले गए सभी बंदरगाह तब तक मुक्त नहीं होंगे जब तक कि सभी तैयार प्रक्रियाएं समाप्त न हों। WScript.Shell मेरी सभी समस्याओं का समाधान किया। यहां उदाहरण: pastebin.com/xGmuvwSx - Alexey Lebedev
आपको CREATE_NEW_PROCESS_GROUP ध्वज की भी आवश्यकता हो सकती है। देख जब तत्काल बच्चे को समाप्त कर दिया जाता है तब भी बच्चे की प्रक्रिया के लिए पॉपन इंतजार कर रहा है - jfs
निम्नलिखित गलत है: "[o] n windows (xp जीतें), पैरेंट प्रक्रिया तब तक समाप्त नहीं होगी जब तक कि longtask.py ने अपना काम पूरा नहीं किया हो"। माता-पिता सामान्य रूप से बाहर निकल जाएंगे, लेकिन कंसोल विंडो (conhost.exe इंस्टेंस) केवल तब बंद हो जाती है जब अंतिम संलग्न प्रक्रिया निकलती है, और बच्चे को माता-पिता के कंसोल को विरासत में मिला हो सकता है। सेटिंग DETACHED_PROCESS में creationflags बच्चे को विरासत में लाने या कंसोल बनाने से रोककर इसे टालता है। यदि आप इसके बजाय एक नया कंसोल चाहते हैं, तो उपयोग करें CREATE_NEW_CONSOLE (0x00000010)। - eryksun
मेरा मतलब यह नहीं था कि एक अलग प्रक्रिया के रूप में निष्पादन गलत है। उस ने कहा, आपको मानक हैंडल को फाइल, पाइप, या पर सेट करने की आवश्यकता हो सकती है os.devnull क्योंकि कुछ कंसोल प्रोग्राम अन्यथा किसी त्रुटि के साथ बाहर निकलते हैं। जब आप बच्चे की प्रक्रिया को मूल प्रक्रिया के साथ उपयोगकर्ता के साथ बातचीत करने की इच्छा रखते हैं तो एक नया कंसोल बनाएं। एक खिड़की में दोनों करने की कोशिश करना भ्रमित होगा। - eryksun


मैं os.system की बजाय उपप्रोसेसर मॉड्यूल का उपयोग करने की सलाह दूंगा क्योंकि यह आपके लिए खोलने से खोलता है और इसलिए यह अधिक सुरक्षित है: http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost'])

98
2017-09-18 01:42





import os
cmd = 'ls -al'
os.system(cmd)

यदि आप कमांड के परिणाम वापस करना चाहते हैं, तो आप इसका उपयोग कर सकते हैं os.popen। हालांकि, इसे संस्करण 2.6 के पक्ष में छोड़ दिया गया है उपप्रोसेसर मॉड्यूल, जो अन्य उत्तरों अच्छी तरह से कवर किया गया है।


94
2017-09-18 01:37



popen पदावनत किया गया है के पक्ष में उपप्रक्रिया। - Fox Wilson
आप ossystem कॉल के साथ अपना परिणाम भी सहेज सकते हैं, क्योंकि यह यूनिक्स शैल की तरह काम करता है, उदाहरण के लिए os.system ('ls -l> test2.txt') - Stefan Gruenwald


import os
os.system("your command")

ध्यान दें कि यह खतरनाक है, क्योंकि आदेश साफ़ नहीं किया गया है। मैं इसे 'ओएस' और 'sys' मॉड्यूल पर प्रासंगिक दस्तावेज के लिए Google पर छोड़ देता हूं। फ़ंक्शन का एक गुच्छा (exec * और spawn *) है जो समान चीजें करेगा।


84
2017-09-18 01:37



आपका क्या मतलब है "आदेश साफ नहीं है"? - Peter Mortensen
मुझे नहीं पता कि मेरा लगभग एक दशक पहले क्या मतलब था (तारीख की जांच करें!), लेकिन अगर मुझे लगता है कि ऐसा कोई मान्यता नहीं है। - nimish