2012-04-11 4 views
26

पर डेटा पास करने के लिए मैं एक स्क्रिप्ट का आह्वान करना चाहता हूं, स्ट्रिंग की सामग्री को अपने stdin पर पाइप करना और इसके stdout को पुनर्प्राप्त करना चाहता हूं।subprocess.check_output

मैं असली फाइल सिस्टम को स्पर्श नहीं करना चाहता हूं इसलिए मैं इसके लिए वास्तविक अस्थायी फ़ाइलें नहीं बना सकता।

subprocess.check_output का उपयोग करके मैं स्क्रिप्ट लिखता हूं; मैं इनपुट स्ट्रिंग को अपने stdin में कैसे प्राप्त कर सकता हूं?

subprocess.check_output([script_name,"-"],stdin="this is some input") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/subprocess.py", line 537, in check_output 
    process = Popen(stdout=PIPE, *popenargs, **kwargs) 
    File "/usr/lib/python2.7/subprocess.py", line 672, in __init__ 
    errread, errwrite) = self._get_handles(stdin, stdout, stderr) 
    File "/usr/lib/python2.7/subprocess.py", line 1043, in _get_handles 
    p2cread = stdin.fileno() 
AttributeError: 'str' object has no attribute 'fileno' 
+2

'check_output()' के लिए 'stdin' arg एक फ़ाइल ऑब्जेक्ट होना चाहिए, स्ट्रिंग नहीं। – jdi

+0

@jdi स्पष्ट रूप से; तो इसे फ़ाइल की तरह कुछ क्वैक कैसे देना है लेकिन फाइल नहीं है? – Will

+0

@larsmans का चयन करके उत्तर :-) यदि आप 'check_output' सुविधा फ़ंक्शन को ओवरस्यूज़ करने का प्रयास नहीं करते हैं और केवल सामान्य पॉपन + संवाद करते हैं तो यह बहुत आसान है। अन्यथा आपको हाथ से पहले मैन्युअल रूप से अपना खुद का पाइप खोलने की उम्मीद की जाएगी, और फिर इसे 'check_output (stdin)' पर पास करें और फिर इसे लिखें। – jdi

उत्तर

29

उपयोग Popen.communicate बजाय subprocess.check_output

from subprocess import Popen, PIPE 

p = Popen([script_name, "-"], stdin=PIPE, stdout=PIPE, stderr=PIPE) 
stdout, stderr = p.communicate("this is some input") 
+0

मुझे इसे काम करने के लिए "-" को हटाना पड़ा –

17

अजगर 3.4 और नए, आप STDIN के माध्यम से इनपुट भेजने के लिए इनपुट कीवर्ड पैरामीटर का उपयोग कर सकते में जब subprocess.check_output()

the standard library documentation for subprocess.check_output() से हवाला देते हुए का उपयोग कर:

इनपुट तर्क है Popen.communicate() और इस प्रकार उपप्रोसेस के stdin को पास किया गया। यदि उपयोग किया जाता है तो यह एक बाइट अनुक्रम होना चाहिए, या universal_newlines=True पर एक स्ट्रिंग होना चाहिए। उपयोग किए जाने पर, आंतरिक Popen ऑब्जेक्ट स्वचालित रूप से stdin=PIPE के साथ बनाया गया है, और stdin तर्क भी उपयोग नहीं किया जा सकता है।

उदाहरण:

>>> subprocess.check_output(["sed", "-e", "s/foo/bar/"], 
...       input=b"when in the course of fooman events\n") 
b'when in the course of barman events\n' 
>>> 
>>> # To send and receive strings instead of bytes, 
>>> # pass in universal_newlines=True 
>>> subprocess.check_output(["sed", "-e", "s/foo/bar/"], 
...       universal_newlines=True, 
...       input="when in the course of fooman events\n") 
'when in the course of barman events\n' 
4

यहाँ इनपुट के साथ अजगर 2.7 के लिए एक check_output बैकपोर्टेड संस्करण है।

from subprocess import (PIPE, Popen, CalledProcessError) 

def check_output_input(*popenargs, **kwargs): 
    """Run command with arguments and return its output as a byte string. 

    If the exit code was non-zero it raises a CalledProcessError. The 
    CalledProcessError object will have the return code in the returncode 
    attribute and output in the output attribute. 

    The arguments are the same as for the Popen constructor. Example: 

    >>> check_output(["ls", "-l", "/dev/null"]) 
    'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 

    The stdout argument is not allowed as it is used internally. 
    To capture standard error in the result, use stderr=STDOUT. 

    >>> check_output(["/bin/sh", "-c", 
    ...    "ls -l non_existent_file ; exit 0"], 
    ...    stderr=STDOUT) 
    'ls: non_existent_file: No such file or directory\n' 

    There is an additional optional argument, "input", allowing you to 
    pass a string to the subprocess's stdin. If you use this argument 
    you may not also use the Popen constructor's "stdin" argument, as 
    it too will be used internally. Example: 

    >>> check_output(["sed", "-e", "s/foo/bar/"], 
    ...    input=b"when in the course of fooman events\n") 
    b'when in the course of barman events\n' 

    If universal_newlines=True is passed, the return value will be a 
    string rather than bytes. 

    """ 
    if 'stdout' in kwargs: 
     raise ValueError('stdout argument not allowed, it will be overridden.') 
    if 'input' in kwargs: 
     if 'stdin' in kwargs: 
      raise ValueError('stdin and input arguments may not both be used.') 
     inputdata = kwargs['input'] 
     del kwargs['input'] 
     kwargs['stdin'] = PIPE 
    else: 
     inputdata = None 
    process = Popen(*popenargs, stdout=PIPE, **kwargs) 
    try: 
     output, unused_err = process.communicate(inputdata) 
    except: 
     process.kill() 
     process.wait() 
     raise 
    retcode = process.poll() 
    if retcode: 
     cmd = kwargs.get("args") 
     if cmd is None: 
      cmd = popenargs[0] 
     raise CalledProcessError(retcode, cmd, output=output) 
    return output