Python 3.7

Subprocesses




python

Subprocesses

यह खंड उप-प्रक्रम बनाने और प्रबंधित करने के लिए उच्च-स्तरीय async / प्रतीक्षा asyncio API का वर्णन करता है।

इस बात का एक उदाहरण है कि कैसे asyncio एक शेल कमांड चला सकता है और उसका परिणाम प्राप्त कर सकता है:

import asyncio

async def run(cmd):
    proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        print(f'[stdout]\n{stdout.decode()}')
    if stderr:
        print(f'[stderr]\n{stderr.decode()}')

asyncio.run(run('ls /zzz'))

प्रिंट होगा:

['ls /zzz' exited with 1]
[stderr]
ls: /zzz: No such file or directory

क्योंकि सभी asyncio उपप्रकार कार्य अतुल्यकालिक हैं और asyncio ऐसे कार्यों के साथ काम करने के लिए कई उपकरण प्रदान करता है, समानांतर में कई उपप्रकारों को निष्पादित और मॉनिटर करना आसान है। एक साथ कई कमांड चलाने के लिए उपरोक्त उदाहरण को संशोधित करना वास्तव में मामूली है:

async def main():
    await asyncio.gather(
        run('ls /zzz'),
        run('sleep 1; echo "hello"'))

asyncio.run(main())

Examples भी देखें।

उपप्रकारों का निर्माण

coroutine asyncio.create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, **kwds)

एक उपप्रकार बनाएँ।

सीमा तर्क Process.stdout और Process.stderr लिए StreamReader रैपर के लिए बफर सीमा निर्धारित करता है (यदि subprocess.PIPE को stdout और Stderr तर्कों को पास किया जाता है)।

एक Process उदाहरण लौटें।

अन्य मापदंडों के लिए loop.subprocess_exec() का प्रलेखन देखें।

coroutine asyncio.create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, **kwds)

Cmd शेल कमांड चलाएं।

सीमा तर्क Process.stdout और Process.stderr लिए StreamReader रैपर के लिए बफर सीमा निर्धारित करता है (यदि subprocess.PIPE को stdout और Stderr तर्कों को पास किया जाता है)।

एक Process उदाहरण लौटें।

अन्य मापदंडों के लिए loop.subprocess_shell() का प्रलेखन देखें।

जरूरी

यह सुनिश्चित करने के लिए आवेदन की ज़िम्मेदारी है कि शेल इंजेक्शन भेद्यता से बचने के लिए सभी व्हाट्सएप और विशेष पात्रों को उचित रूप से उद्धृत किया गया है। shlex.quote() फ़ंक्शन का उपयोग शेल कमांड के निर्माण के लिए उपयोग किए जाने वाले स्ट्रिंग्स में shlex.quote() और विशेष शेल वर्णों को ठीक से बचने के लिए किया जा सकता है।

ध्यान दें

डिफ़ॉल्ट asyncio इवेंट लूप कार्यान्वयन विंडोज पर उपप्रोसेस का समर्थन नहीं करता है। यदि ProactorEventLoop का उपयोग किया जाता है, तो Windows के लिए ProactorEventLoop उपलब्ध हैं। विवरण के लिए विंडोज पर उपप्रक्रम समर्थन देखें।

यह भी देखें

asyncio में सबप्रोसेस के साथ काम करने के लिए निम्न निम्न-स्तर के API भी हैं: loop.subprocess_exec() , loop.subprocess_shell() , loop.connect_read_pipe() , loop.connect_write_pipe() , साथ ही साथ loop.connect_write_pipe() Transports और Subprocess Protocols

स्थिरांक

asyncio.subprocess.PIPE

स्टडिन , स्टडआउट या स्टेडर मापदंडों को पारित किया जा सकता है।

यदि PIPE को स्टडिन तर्क के लिए पास किया जाता है, तो Process.stdin विशेषता StreamWriter उदाहरण की ओर इंगित करेगी।

यदि PIPE को stdout या Stderr तर्कों के लिए पास किया जाता है, तो Process.stdout और Process.stderr विशेषताएँ StreamReader उदाहरणों की ओर इंगित करेंगी।

asyncio.subprocess.STDOUT

विशेष मूल्य जिसे स्टैडर तर्क के रूप में इस्तेमाल किया जा सकता है और यह दर्शाता है कि मानक त्रुटि को मानक आउटपुट में पुनर्निर्देशित किया जाना चाहिए।

asyncio.subprocess.DEVNULL

विशेष मूल्य जो निर्माण कार्यों को संसाधित करने के लिए स्टड , स्टडआउट या स्टेडर तर्क के रूप में उपयोग किया जा सकता है। यह इंगित करता है कि संबंधित os.devnull धारा के लिए विशेष फ़ाइल os.devnull का उपयोग किया जाएगा।

उपप्रकारों के साथ बातचीत

दोनों create_subprocess_exec() और create_subprocess_shell() फ़ंक्शंस प्रक्रिया वर्ग के उदाहरण लौटाते हैं। प्रक्रिया एक उच्च-स्तरीय आवरण है जो उपप्रकारों के साथ संचार करने और उनके पूरा होने की अनुमति देता है।

class asyncio.subprocess.Process

एक ऑब्जेक्ट जो create_subprocess_exec() और create_subprocess_shell() फ़ंक्शन द्वारा बनाई गई OS प्रक्रियाओं को लपेटता है।

इस वर्ग को subprocess.Popen लिए एक समान एपीआई के लिए डिज़ाइन किया गया है। subprocess.Popen क्लास, लेकिन कुछ उल्लेखनीय अंतर हैं:

  • पोपेन के विपरीत, प्रक्रिया के उदाहरणों में poll() विधि के बराबर नहीं है;
  • communicate() और wait() विधियों में टाइमआउट पैरामीटर नहीं है: wait_for() फ़ंक्शन का उपयोग करें;
  • wait() विधि अतुल्यकालिक है, जबकि subprocess.Popen.wait() विधि एक अवरुद्ध व्यस्त लूप के रूप में कार्यान्वित की जाती है;
  • Universal_newlines पैरामीटर समर्थित नहीं है।

यह वर्ग धागा सुरक्षित नहीं है

सबप्रोसेस और थ्रेड्स अनुभाग भी देखें।

coroutine wait()

बच्चे की प्रक्रिया समाप्त होने तक प्रतीक्षा करें।

सेट करें और वापसी की विशेषता।

ध्यान दें

इस विधि को गतिरोध में उपयोग करते समय गतिरोध किया जा सकता है stdout=PIPE या stderr=PIPE और बच्चे की प्रक्रिया इतनी अधिक आउटपुट उत्पन्न करती है कि वह अधिक डेटा स्वीकार करने के लिए OS पाइप बफर के इंतजार में ब्लॉक हो जाता है। इस स्थिति से बचने के लिए पाइप का उपयोग करते समय communicate() विधि का उपयोग करें।

coroutine communicate(input=None)

प्रक्रिया के साथ बातचीत करें:

  1. स्टडिन को डेटा भेजें (यदि इनपुट कोई None );
  2. EOF तक पहुंचने तक स्टडआउट और स्टेडर से डेटा पढ़ें;
  3. प्रक्रिया समाप्त होने की प्रतीक्षा करें।

वैकल्पिक इनपुट तर्क वह डेटा ( bytes ऑब्जेक्ट) है जिसे बाल प्रक्रिया में भेजा जाएगा।

एक टपल लौटें (stdout_data, stderr_data)

यदि BrokenPipeError में इनपुट लिखते समय BrokenPipeError या ConnectionResetError अपवाद उठाया जाता है, तो अपवाद को अनदेखा कर दिया जाता है। यह स्थिति तब होती है जब सभी डेटा स्टड में लिखे जाने से पहले प्रक्रिया बाहर निकल जाती है।

यदि यह प्रक्रिया ' स्टडिन ' को डेटा भेजने के लिए वांछित है, तो प्रक्रिया को stdin=PIPE के साथ बनाने की आवश्यकता है। इसी तरह, परिणाम ट्यूपल में किसी के अलावा कुछ भी प्राप्त करने के लिए, प्रक्रिया को stdout=PIPE और / या stderr=PIPE तर्कों के साथ बनाया जाना चाहिए।

ध्यान दें, कि पढ़ा गया डेटा मेमोरी में बफर्ड है, इसलिए डेटा साइज़ बड़ा या अनलिमिटेड होने पर इस तरीके का इस्तेमाल न करें।

send_signal(signal)

चाइल्ड प्रोसेस को सिग्नल सिग्नल भेजता है।

ध्यान दें

विंडोज पर, SIGTERM terminate() लिए एक उपनाम है। CTRL_C_EVENT और CTRL_BREAK_EVENT को CTRL_BREAK_EVENT पैरामीटर के साथ शुरू की गई प्रक्रियाओं में भेजा जा सकता है जिसमें CREATE_NEW_PROCESS_GROUP शामिल है।

terminate()

बच्चे की प्रक्रिया को रोकें।

POSIX सिस्टम पर यह विधि संतान प्रक्रिया को signal.SIGTERM भेजती है।

Windows पर Win32 API फ़ंक्शन TerminateProcess() को चाइल्ड प्रोसेस को रोकने के लिए कहा जाता है।

kill()

बच्चे को मार डालो।

POSIX सिस्टम पर यह विधि SIGKILL को चाइल्ड प्रोसेस में भेजती है।

विंडोज पर यह विधि terminate() लिए एक उपनाम है।

stdin

मानक इनपुट स्ट्रीम ( StreamWriter ) या None अगर प्रक्रिया stdin=None के साथ बनाई गई थी।

stdout

मानक आउटपुट स्ट्रीम ( StreamReader ) या None अगर प्रक्रिया stdout=None के साथ बनाई गई थी stdout=None

stderr

मानक त्रुटि धारा ( StreamReader ) या None तो प्रक्रिया stderr=None के साथ बनाई गई थी stderr=None

चेतावनी

Process.stdin बजाय communicate() विधि का प्रयोग करें, Process.stdout या Process.stderr . Process.stderr । यह पढ़ने या लिखने और बच्चे की प्रक्रिया को रोकने की धाराओं के कारण गतिरोध से बचा जाता है।

pid

प्रक्रिया पहचान संख्या (पीआईडी)।

ध्यान दें कि create_subprocess_shell() फ़ंक्शन द्वारा बनाई गई प्रक्रियाओं के लिए, यह विशेषता create_subprocess_shell() शेल का पीआईडी ​​है।

returncode

जब यह बाहर निकलता है तो प्रक्रिया का रिटर्न कोड।

कोई None मान इंगित None करता है कि प्रक्रिया अभी तक समाप्त नहीं हुई है।

एक नकारात्मक मान -N इंगित करता है कि बच्चे को संकेत N (पोसिक्स केवल) द्वारा समाप्त किया गया था।

उपप्रकार और धागे

मानक asyncio इवेंट लूप विभिन्न थ्रेड्स से उपप्रोसेस चलाने का समर्थन करता है, लेकिन सीमाएँ हैं:

  • ईवेंट लूप मुख्य थ्रेड में चलना चाहिए।
  • अन्य थ्रेड्स से सबप्रोसेस को निष्पादित करने से पहले बच्चे पर नजर रखने वाले को मुख्य थ्रेड में त्वरित किया जाना चाहिए। मुख्य get_child_watcher() में get_child_watcher() फ़ंक्शन को कॉल करें get_child_watcher() बच्चे पर नजर get_child_watcher() जा get_child_watcher()

ध्यान दें कि वैकल्पिक ईवेंट लूप कार्यान्वयन उपरोक्त सीमाओं को साझा नहीं कर सकता है; कृपया उनके दस्तावेज देखें।

उदाहरण

अपने मानक आउटपुट से पढ़ने के लिए StreamReader और स्ट्रीमराइडर क्लास को नियंत्रित करने के लिए Process क्लास का उपयोग करने वाला एक उदाहरण।

उपप्रक्रम create_subprocess_exec() फ़ंक्शन द्वारा बनाया गया है:

import asyncio
import sys

async def get_date():
    code = 'import datetime; print(datetime.datetime.now())'

    # Create the subprocess; redirect the standard output
    # into a pipe.
    proc = await asyncio.create_subprocess_exec(
        sys.executable, '-c', code,
        stdout=asyncio.subprocess.PIPE)

    # Read one line of output.
    data = await proc.stdout.readline()
    line = data.decode('ascii').rstrip()

    # Wait for the subprocess exit.
    await proc.wait()
    return line

if sys.platform == "win32":
    asyncio.set_event_loop_policy(
        asyncio.WindowsProactorEventLoopPolicy())

date = asyncio.run(get_date())
print(f"Current date: {date}")

निम्न-स्तरीय API का उपयोग करके लिखा गया उदाहरण भी देखें।