एक स्ट्रिंग में subprocess.Popen कॉल का स्टोर आउटपुट


300

मैं पायथन में एक सिस्टम कॉल करने और आउटपुट को एक स्ट्रिंग में स्टोर करने की कोशिश कर रहा हूं जिसे मैं पायथन प्रोग्राम में हेरफेर कर सकता हूं।

#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")

मैंने कुछ सुझावों की कोशिश की है, जिनमें से कुछ सुझाव यहाँ दिए गए हैं:

Subprocess.call () के आउटपुट को पुनः प्राप्त करना

लेकिन बिना किसी भाग्य के।


3
आपके द्वारा चलाए गए वास्तविक कोड और वास्तविक ट्रेसबैक या इस तरह के ठोस प्रश्नों के लिए अप्रत्याशित bahaviour पोस्ट करना हमेशा अच्छा होता है। उदाहरण के लिए, मुझे नहीं पता कि आपने आउटपुट प्राप्त करने के लिए क्या करने की कोशिश की है और मुझे संदेह है कि आपको वास्तव में ऐसा नहीं करना था, जिसके साथ शुरुआत करने के लिए - आपको फ़ाइल खोजने में कोई त्रुटि नहीं मिली होगी "ntpq -p", जो इसका एक अलग हिस्सा है इस समस्या से आप के बारे में पूछ रहे हैं।
माइक ग्राहम

जवाबों:


467

पायथन 2.7 या पायथन 3 में

Popenसीधे ऑब्जेक्ट बनाने के बजाय , आप एक स्ट्रिंग में कमांड के आउटपुट को स्टोर करने के लिए subprocess.check_output()फ़ंक्शन का उपयोग कर सकते हैं :

from subprocess import check_output
out = check_output(["ntpq", "-p"])

पायथन में 2.4-2.6

communicateविधि का प्रयोग करें ।

import subprocess
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE)
out, err = p.communicate()

out तुम क्या चाहते हो

अन्य उत्तरों के बारे में महत्वपूर्ण सूचना

ध्यान दें कि मैं कमांड में कैसे पारित हुआ। "ntpq -p"उदाहरण के लिए एक और बात सामने आती है। चूंकि Popenशेल का आह्वान नहीं करता है, आप कमांड और विकल्पों की एक सूची का उपयोग करेंगे- ["ntpq", "-p"]


3
इस मामले में, क्या अजगर इस सिस्टम कॉल के खत्म होने का इंतजार करता है? या यह प्रतीक्षा / वेटपिड फ़ंक्शन को स्पष्ट रूप से कॉल करने के लिए आवश्यक है?
बजे कोई नहीं २

7
@NoneType, Popen.communicateप्रक्रिया समाप्त होने तक वापस नहीं आता है।
माइक ग्राहम

10
अगर आप एरर स्ट्रीम जोड़ना चाहते हैं तो stderr जोड़ें:p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Timofey

82
सावधान, subprocess.check_output()एक bytesवस्तु देता है , नहीं str। यदि आप सब करना चाहते हैं तो परिणाम प्रिंट करें, इससे कोई फर्क नहीं पड़ेगा। लेकिन अगर आप myString.split("\n")परिणाम जैसे विधि का उपयोग करना चाहते हैं , तो आपको सबसे पहले bytesऑब्जेक्ट को डिकोड करना होगा : subprocess.check_output(myParams).decode("utf-8")उदाहरण के लिए।
टंगूपी

17
universal_newlines=Trueएक पैरामीटर के रूप में जोड़ने से मुझे स्ट्रिंग ऑब्जेक्ट प्राप्त करने में पायथन 3 में मदद मिली। यदि Universal_newlines सत्य है, तो उन्हें डिफ़ॉल्ट एन्कोडिंग के साथ पाठ मोड में खोला जाता है। अन्यथा, उन्हें बाइनरी धाराओं के रूप में खोला जाता है।
जोनाथन कोमर

38

यह मेरे लिए काम करने के लिए पुनर्निर्देशन stdout (stderr समान रूप से संभाला जा सकता है):

from subprocess import Popen, PIPE
pipe = Popen(path, stdout=PIPE)
text = pipe.communicate()[0]

यदि यह आपके लिए काम नहीं करता है, तो कृपया ठीक वही समस्या निर्दिष्ट करें जो आप कर रहे हैं।


3
यह कुछ अजीब वस्तु का उत्पादन करता है। जब मैं इसे स्ट्रिंग में परिवर्तित करता हूं, तो यह व्हॉट्सएप से बच जाता है \n
टॉम ज़ातो -

1
ध्यान दें कि यह जाँच नहीं करता है कि क्या उपप्रकार सही ढंग से चला। आप शायद यह देखना चाहते हैं कि pipe.returncode == 0अंतिम पंक्ति के बाद भी।
थकीज

कारण यह काम करता है क्योंकि है Popenरिटर्न की एक टपल stdoutऔर stderrइसलिए जब आप का उपयोग, [0]तुम सिर्फ हथियाने रहे हैं stdout। आप यह भी कर सकते हैं text, err = pipe.communicate()और फिर textआपके पास उम्मीद होगी
जोना


22

subprocess.Popen: http://docs.python.org/2/library/subprocess.html#subproth.Popen

import subprocess

command = "ntpq -p"  # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True)

#Launch the shell command:
output = process.communicate()

print output[0]

Popen निर्माता में, यदि खोल है यह सच है , तो आप आदेश स्ट्रिंग के रूप के बजाय एक दृश्य के रूप में पास करना चाहिए। अन्यथा, बस कमांड को एक सूची में विभाजित करें:

command = ["ntpq", "-p"]  # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None)

आप भी मानक त्रुटि, popen प्रारंभ में पढ़ने की जरूरत है, तो आप सेट कर सकते हैं stderr को subprocess.PIPE या करने के लिए subprocess.STDOUT :

import subprocess

command = "ntpq -p"  # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

#Launch the shell command:
output, error = process.communicate()

भययोग्य यह है कि मैं क्या देख रहा था
kRazzy R

14

पायथन 2.7+ के लिए मुहावरेदार उत्तर का उपयोग करना है subprocess.check_output()

आपको उपप्रकार को लागू करते समय तर्कों की हैंडलिंग पर भी ध्यान देना चाहिए, क्योंकि यह थोड़ा भ्रमित हो सकता है ...।

यदि आर्ग्स केवल एकल कमांड है जिसका कोई भी आर्गन्स नहीं है (या आपने shell=Trueसेट किया है), तो यह एक स्ट्रिंग हो सकता है। अन्यथा यह एक सूची होनी चाहिए।

उदाहरण के लिए ... lsआदेश को लागू करने के लिए , यह ठीक है:

from subprocess import check_call
check_call('ls')

ऐसा है:

from subprocess import check_call
check_call(['ls',])

हालाँकि, यदि आप शेल कमांड में कुछ आर्गन्स पास करना चाहते हैं, तो आप ऐसा नहीं कर सकते :

from subprocess import check_call
check_call('ls -al')

इसके बजाय, आपको इसे सूची के रूप में पास करना होगा:

from subprocess import check_call
check_call(['ls', '-al'])

shlex.split()समारोह कभी कभी-जैसा शेल वाक्य रचना एक subprocesses बनाने ... इस तरह से पहले में एक स्ट्रिंग को विभाजित करने के लिए उपयोगी हो सकते हैं:

from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))

पांच साल बाद, इस सवाल को अभी भी बहुत प्यार मिल रहा है। 2.7+ अपडेट के लिए धन्यवाद, कोरी!
मार्क

11

यह मेरे लिए पूरी तरह से काम करता है:

import subprocess
try:
    #prints results and merges stdout and std
    result = subprocess.check_output("echo %USERNAME%", stderr=subprocess.STDOUT, shell=True)
    print result
    #causes error and merges stdout and stderr
    result = subprocess.check_output("copy testfds", stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError, ex: # error code <> 0 
    print "--------error------"
    print ex.cmd
    print ex.message
    print ex.returncode
    print ex.output # contains stdout and stderr together 

9

यह मेरे लिए एकदम सही था। आपको एक ट्यूपल में रिटर्न कोड, स्टडआउट और स्टेडर मिलेगा।

from subprocess import Popen, PIPE

def console(cmd):
    p = Popen(cmd, shell=True, stdout=PIPE)
    out, err = p.communicate()
    return (p.returncode, out, err)

उदाहरण के लिए:

result = console('ls -l')
print 'returncode: %s' % result[0]
print 'output: %s' % result[1]
print 'error: %s' % result[2]

6

स्वीकृत उत्तर अभी भी अच्छा है, नई सुविधाओं पर सिर्फ कुछ टिप्पणी। अजगर 3.6 के बाद से, आप सीधे एन्कोडिंग को संभाल सकते check_outputहैं, प्रलेखन देखें । यह अब एक स्ट्रिंग ऑब्जेक्ट लौटाता है:

import subprocess 
out = subprocess.check_output(["ls", "-l"], encoding="utf-8")

capture_outputPython 3.7 में, एक पैरामीटर को subprocess.run () में जोड़ा गया था, जो हमारे लिए कुछ पोपेन / PIPE हैंडलिंग करता है, अजगर डॉक्स देखें :

import subprocess 
p2 = subprocess.run(["ls", "-l"], capture_output=True, encoding="utf-8")
p2.stdout

4
 import os   
 list = os.popen('pwd').read()

इस मामले में आपके पास सूची में केवल एक तत्व होगा।


7
os.popensubprocessमॉड्यूल के पक्ष में पदावनत किया जाता है ।
माइक ग्राहम

3
पायथन की 2.2.X श्रृंखला का उपयोग करके एक पुराने बॉक्स पर व्यवस्थापक के लिए यह काफी मददगार था।
नील मैकफ़

4

मैंने अन्य उत्तरों के आधार पर एक छोटा सा कार्य लिखा है:

def pexec(*args):
    return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip()

उपयोग:

changeset = pexec('hg','id','--id')
branch = pexec('hg','id','--branch')
revnum = pexec('hg','id','--num')
print('%s : %s (%s)' % (revnum, changeset, branch))

4

पायथॉन 3.7 में एक नया कीवर्ड तर्क capture_outputपेश किया गया था subprocess.run। छोटे और सरल को सक्षम करना:

import subprocess

p = subprocess.run("echo 'hello world!'", capture_output=True, shell=True, encoding="utf8")
assert p.stdout == 'hello world!\n'


0

निम्नलिखित एक ही चर में प्रक्रिया के stdout और stderr को कैप्चर करता है। यह पायथन 2 और 3 संगत है:

from subprocess import check_output, CalledProcessError, STDOUT

command = ["ls", "-l"]
try:
    output = check_output(command, stderr=STDOUT).decode()
    success = True 
except CalledProcessError as e:
    output = e.output.decode()
    success = False

यदि आपका कमांड एक सरणी के बजाय एक स्ट्रिंग है, तो इसके साथ उपसर्ग करें:

import shlex
command = shlex.split(command)

0

अजगर 3.5 के लिए मैंने पिछले उत्तर के आधार पर कार्य किया। लॉग हटाया जा सकता है, सोचा कि यह अच्छा है

import shlex
from subprocess import check_output, CalledProcessError, STDOUT


def cmdline(command):
    log("cmdline:{}".format(command))
    cmdArr = shlex.split(command)
    try:
        output = check_output(cmdArr,  stderr=STDOUT).decode()
        log("Success:{}".format(output))
    except (CalledProcessError) as e:
        output = e.output.decode()
        log("Fail:{}".format(output))
    except (Exception) as e:
        output = str(e);
        log("Fail:{}".format(e))
    return str(output)


def log(msg):
    msg = str(msg)
    d_date = datetime.datetime.now()
    now = str(d_date.strftime("%Y-%m-%d %H:%M:%S"))
    print(now + " " + msg)
    if ("LOG_FILE" in globals()):
        with open(LOG_FILE, "a") as myfile:
            myfile.write(now + " " + msg + "\n")

0

की ckeck_outputविधि का प्रयोग करेंsubprocess

import subprocess
address = 192.168.x.x
res = subprocess.check_output(['ping', address, '-c', '3'])

अंत में स्ट्रिंग पार्स

for line in res.splitlines():

आशा है कि यह मदद करता है, खुश कोडिंग

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.