প্রক্রিয়া চলমান অবস্থায় ধারাবাহিকভাবে সাবপ্রসেস আউটপুট মুদ্রণ করুন


201

আমার পাইথন-স্ক্রিপ্টগুলি থেকে প্রোগ্রামগুলি চালু করতে, আমি নিম্নলিখিত পদ্ধতিটি ব্যবহার করছি:

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

সুতরাং আমি যখন কোনও প্রক্রিয়া চালু করি তখন Process.execute("mvn clean install")প্রক্রিয়াটি শেষ না হওয়া পর্যন্ত আমার প্রোগ্রামটি অপেক্ষা করে এবং কেবল তখনই আমি আমার প্রোগ্রামটির সম্পূর্ণ আউটপুট পাই। এটি বিরক্তিকর যদি আমি এমন একটি প্রক্রিয়া চালাচ্ছি যা শেষ করতে কিছুটা সময় নেয়।

আমি কি আমার প্রোগ্রামটিকে লুপ বা কোনও কিছু শেষ করার আগে প্রক্রিয়া আউটপুটকে ভোট দিয়ে লাইন দিয়ে প্রক্রিয়া আউটপুট লাইন লিখতে পারি?

** [সম্পাদনা] দুঃখিত এই প্রশ্নটি পোস্ট করার আগে আমি খুব ভালভাবে অনুসন্ধান করিনি। থ্রেডিং আসলে মূল চাবিকাঠি। এটির জন্য এখানে একটি উদাহরণ পাওয়া গেছে যা এটি কীভাবে করতে হবে তা দেখায়: ** পাইথন সাবপ্রসেস a থ্রেড থেকে প্রকাশিত


Subprocess পরিবর্তে থ্রেড আমি মনে করি
অ্যান্ট

9
না, আপনার থ্রেডের দরকার নেই। পুরো পাইপিং আইডিয়াটি কাজ করে কারণ আপনি যখন চলতে থাকেন তখন প্রক্রিয়াগুলি থেকে পড়তে / লিখতে পারেন।
টোকল্যান্ড

উত্তর:


264

আপনি ব্যবহার করতে পারেন রাউটার : শীঘ্রই কমান্ড আউটপুট তাদের যত লাইন প্রক্রিয়া lines = iter(fd.readline, "")। এখানে একটি সাধারণ ব্যবহারের কেস দেখানোর একটি সম্পূর্ণ উদাহরণ রয়েছে (@ জেফএসকে সাহায্য করার জন্য ধন্যবাদ):

from __future__ import print_function # Only Python 2.x
import subprocess

def execute(cmd):
    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
    for stdout_line in iter(popen.stdout.readline, ""):
        yield stdout_line 
    popen.stdout.close()
    return_code = popen.wait()
    if return_code:
        raise subprocess.CalledProcessError(return_code, cmd)

# Example
for path in execute(["locate", "a"]):
    print(path, end="")

24
আমি এই কোডটি চেষ্টা করেছি (এমন একটি প্রোগ্রামের সাথে যা চালাতে গুরুত্বপূর্ণ সময় লাগে) এবং মৃত্যুদন্ড কার্যকর হওয়ার অপেক্ষা না করে লাইনগুলি প্রাপ্ত হওয়ার সাথে সাথে এটি নিশ্চিত করতে পারে। এটি উচ্চতর উত্তর ইমো।
অ্যান্ড্রু মার্টিন

11
দ্রষ্টব্য: পাইথন 3 এ, আপনি ব্যবহার করতে পারেন for line in popen.stdout: print(line.decode(), end='')। পাইথন 2 এবং 3 উভয় সমর্থন করতে, বাইটস আক্ষরিক ব্যবহার করুন: b''অন্যথায় lines_iteratorপাইথন 3 এ কখনও শেষ হয় না
jfs

3
এই পদ্ধতির সমস্যাটি হ'ল প্রক্রিয়াটি স্টাডাউটকে কিছু না লিখে কিছুক্ষণ বিরতি দেয় তবে পড়ার আর কোনও ইনপুট নেই। প্রক্রিয়াটি শেষ হয়েছে কিনা তা পরীক্ষা করার জন্য আপনাকে একটি লুপের প্রয়োজন হবে। অজগর ২.7
হার

7
এটি কাজ করা উচিত. এটি পোলিশ করতে, আপনি যোগ করতে পারেন bufsize=1(এটি পাইথন 2 এর পারফরম্যান্সের উন্নতি করতে পারে), popen.stdoutপরিষ্কারভাবে পাইপটি বন্ধ করুন (আবর্জনা সংগ্রহের জন্য এটির যত্ন নেওয়ার অপেক্ষা না করে), এবং উত্থাপন subprocess.CalledProcessError(যেমন check_call(), check_output()করুন) করতে পারেন। printপাইথন 2 এবং 3 এ বিবৃতিটি ভিন্ন: আপনি বাইটস সম্পর্কিত উত্তরের পরিবর্তে পাঠ্য পেতে print line,আপনার কোডের মতো সমস্ত নিউলাইনটি দ্বিগুণ করা এবং universal_newlines=Trueপাইথন 3 এ পাশ করা এড়াতে আপনি সফটস্পেস হ্যাক (নোট: কমা) ব্যবহার করতে পারেন ।
jfs

6
@ বিনজহং এটি কোনও ত্রুটি নয়, স্টাইডাউটটি পাইথন স্ক্রিপ্টগুলিতে ডিফল্টভাবে বাফার হয় (অনেকগুলি ইউনিক্স সরঞ্জামের জন্যও)। ব্যবহার করে দেখুন execute(["python", "-u", "child_thread.py"])। আরো তথ্য: stackoverflow.com/questions/14258500/...
tokland

84

ঠিক আছে আমি থ্রেড ছাড়াই এটি সমাধান করতে সক্ষম হলাম (থ্রেডগুলি ব্যবহারের কেন আরও ভাল প্রশংসা করা হবে এমন কোনও পরামর্শ) এই প্রশ্নটি থেকে একটি স্নিপেট ব্যবহার করে এটি চলমান অবস্থায় সাব-প্রসেসের স্টাডাউটকে বাধা দিচ্ছে

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline()
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

3
মার্জ ifischer এবং tokland এর কোড বেশ ভাল কাজ করে (আমি পরিবর্তন করতে হয়েছে print line,থেকে sys.stdout.write(nextline); sys.stdout.flush()। অন্যথায়, এটি প্রতি দুই লাইন প্রিন্ট আউট হবে তারপর আবার, এই IPython এর নোটবুক ইন্টারফেস ব্যবহার করা হয়, তাই হয়তো অন্য কিছু ঘটছে -। নির্বিশেষে স্পষ্টভাবে কলিং flush()কাজ করে।
eacousineau

3
মিস্টার তুমি আমার জীবন রক্ষাকারী !! সত্যিই অদ্ভুত জিনিষ এই ধরনের হয় না বিল্ড-ইন লাইব্রেরিতে নিজেই .. কারণ আমি যদি cliapp লিখুন, আমি সবকিছু কি সঙ্গে সঙ্গে .. s'rsly .. লুপ প্রক্রিয়াকরণের এর দেখাতে চান
holms

3
এই সমাধানটি আউটপুট এবং ত্রুটি উভয়ই মুদ্রণের জন্য সংশোধন করা যেতে পারে? যদি আমি পরিবর্তন stderr=subprocess.STDOUTকরতে stderr=subprocess.PIPEএবং তারপর কল process.stderr.readline()লুপ মধ্যে থেকে, আমি খুব এর afoul চালানোর অচলাবস্থা যে জন্য ডকুমেন্টেশনে সম্পর্কে সতর্ক করা হয় বলে মনে হচ্ছে subprocessমডিউল।
ডেভিডর্মচার্স

7
@ ডেভিডচারেলস আমি মনে করি আপনি যা খুঁজছেন তা stdout=subprocess.PIPE,stderr=subprocess.STDOUTএই স্ট্যাডারকে ক্যাপচার করে, এবং আমি বিশ্বাস করি (তবে আমি পরীক্ষা করিনি) এটি স্ট্যান্ডিনকেও বন্দী করে।
অ্যান্ড্রু মার্টিন

প্রস্থান কোড জন্য অপেক্ষা করার জন্য ধন্যবাদ। কীভাবে এটি কাজ করবেন তা জানতেন না
ভিটালি Isaশায়েভ

67

সাব-প্রসেসের আউটপুট লাইন বাই লাইন মুদ্রণ করতে তার স্টাডআউট বাফারটি পাইথন 3 এ ফ্লাশ করা মাত্র:

from subprocess import Popen, PIPE, CalledProcessError

with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
    for line in p.stdout:
        print(line, end='') # process line here

if p.returncode != 0:
    raise CalledProcessError(p.returncode, p.args)

বিজ্ঞপ্তি: আপনার প্রয়োজন নেই p.poll()- লুফটি ইওফ পৌঁছে গেলে শেষ হয়। এবং আপনার প্রয়োজন নেই iter(p.stdout.readline, '')- পঠন-পরবর্তী বাগটি পাইথন 3 এ স্থির করা হয়েছে।

পাইথন আরও দেখুন : সাবপ্রসেস ডটকমিটিকেট () থেকে স্ট্রিমিং ইনপুট পড়ুন


3
এই সমাধানটি আমার পক্ষে কাজ করেছিল। উপরে প্রদত্ত স্বীকৃত সমাধানটি আমার জন্য খালি লাইনগুলি মুদ্রণ করতে গিয়েছিল।
কোডনাম

3
আমার সাথে সাথে প্রিন্ট পেতে sys.stdout.flush () যুক্ত করতে হবে।
কোডনাম

3
@ কোডনাম: আপনার sys.stdout.flush()পিতামাতার দরকার নেই - স্টডআউট লাইন-বাফার করা হয় যদি এটি কোনও ফাইল / পাইপে পুনর্নির্দেশ না করা হয় এবং তাই lineবাফারটি স্বয়ংক্রিয়ভাবে ফ্লাশ করে fl আপনার sys.stdout.flush()সন্তানের খুব দরকার নেই - -uপরিবর্তে কমান্ড-লাইন বিকল্পটি পাস করুন।
jfs

1
@ কোডনাম: আপনি যদি ব্যবহার করতে চান >তবে চালান python -u your-script.py > some-file। বিজ্ঞপ্তি: -uযে বিকল্পটি আমি উপরে উল্লেখ করেছি (ব্যবহার করার দরকার নেই sys.stdout.flush())।
jfs

1
@ এমভিডেলগৌজ-কে কল করতে হবে p.wait()না withblock এটি ব্লক থেকে প্রস্থান করার জন্য ডাকা হয় । ব্যবহার p.returncode
jfs

8

আপনি কেবল আউটপুট মুদ্রণ করতে চাইলে এটি করার একটি খুব সহজ উপায় আছে :

import subprocess
import sys

def execute(command):
    subprocess.check_call(command, stdout=sys.stdout, stderr=subprocess.STDOUT)

এখানে আমরা কেবল আমাদের নিজস্ব স্টডআউটের দিকে সাবপ্রসেসটি নির্দেশ করছি এবং বিদ্যমান সফল বা ব্যতিক্রম এপিআই ব্যবহার করছি।


1
পাইথন ৩.6 এর জন্য এই সমাধানটি @ টোকল্যান্ডের সমাধানের চেয়ে সহজ এবং পরিষ্কার। আমি লক্ষ্য করেছি যে শেল = সত্য যুক্তিটি প্রয়োজনীয় নয়।
শুভ উইল

গুড ক্যাচ, গুড উইল সরানো হয়েছেshell=True
অ্যান্ড্রু রিং

খুব উদ্বেগজনক এবং সামান্য কোড সহ পুরোপুরি কাজ করে। হতে পারে আপনার সাবপ্রসেস স্টাডারকেও sys.stderr এ পুনর্নির্দেশ করা উচিত?
মনু

মানু তুমি নিশ্চয়ই পারো। আমি এখানে করিনি, কারণ প্রশ্নের চেষ্টাটি স্ট্যাডারকে স্টাডাউটে পুনর্নির্দেশ করছিল।
অ্যান্ড্রু রিং

Sys.stdout এবং subprocess.STDOUT এর মধ্যে পার্থক্যটি কি আপনি ব্যাখ্যা করতে পারেন?
রন সেরুয়া

7

@tokland

আপনার কোডটি চেষ্টা করে 3.4 এর জন্য সংশোধন করা হয়েছে এবং উইন্ডোজ dir.cmd একটি সরল দির কমান্ড, সেমিডি ফাইল হিসাবে সংরক্ষণ

import subprocess
c = "dir.cmd"

def execute(command):
    popen = subprocess.Popen(command, stdout=subprocess.PIPE,bufsize=1)
    lines_iterator = iter(popen.stdout.readline, b"")
    while popen.poll() is None:
        for line in lines_iterator:
            nline = line.rstrip()
            print(nline.decode("latin"), end = "\r\n",flush =True) # yield line

execute(c)

3
আপনি আপনার কোড সহজ করতে পারেন । iter()এবং end='\r\n'অপ্রয়োজনীয়। পাইথন সর্বজনীন নিউলাইনস মোডটি ডিফল্ট হিসাবে ব্যবহার করে অর্থাৎ মুদ্রণের সময় যে কোনওটিতে '\n'অনুবাদ করা '\r\n'হয়। 'latin'সম্ভবত একটি ভুল এনকোডিং, আপনি universal_newlines=Trueপাইথন 3 এ পাঠ্য আউটপুট পেতে ব্যবহার করতে পারেন (লোকেলের পছন্দসই এনকোডিং ব্যবহার করে ডিকোডড)। থামবেন না .poll(), অপঠিত ডেটা বাফার হতে পারে। পাইথন স্ক্রিপ্টটি যদি কোন কনসোলে চলছে তবে এর আউটপুটটি লাইন-বাফার হবে; আপনি -uবিকল্প ব্যবহার করে লাইন-বাফারিং করতে বাধ্য করতে পারেন - আপনার flush=Trueএখানে দরকার নেই।
jfs

4

কেস কেউ উভয় থেকে পড়তে চায় stdoutএবং stderrএকই সময়ে থ্রেড ব্যবহার করে, এই কি আমি নিয়ে এসেছেন হল:

import threading
import subprocess
import Queue

class AsyncLineReader(threading.Thread):
    def __init__(self, fd, outputQueue):
        threading.Thread.__init__(self)

        assert isinstance(outputQueue, Queue.Queue)
        assert callable(fd.readline)

        self.fd = fd
        self.outputQueue = outputQueue

    def run(self):
        map(self.outputQueue.put, iter(self.fd.readline, ''))

    def eof(self):
        return not self.is_alive() and self.outputQueue.empty()

    @classmethod
    def getForFd(cls, fd, start=True):
        queue = Queue.Queue()
        reader = cls(fd, queue)

        if start:
            reader.start()

        return reader, queue


process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdoutReader, stdoutQueue) = AsyncLineReader.getForFd(process.stdout)
(stderrReader, stderrQueue) = AsyncLineReader.getForFd(process.stderr)

# Keep checking queues until there is no more output.
while not stdoutReader.eof() or not stderrReader.eof():
   # Process all available lines from the stdout Queue.
   while not stdoutQueue.empty():
       line = stdoutQueue.get()
       print 'Received stdout: ' + repr(line)

       # Do stuff with stdout line.

   # Process all available lines from the stderr Queue.
   while not stderrQueue.empty():
       line = stderrQueue.get()
       print 'Received stderr: ' + repr(line)

       # Do stuff with stderr line.

   # Sleep for a short time to avoid excessive CPU use while waiting for data.
   sleep(0.05)

print "Waiting for async readers to finish..."
stdoutReader.join()
stderrReader.join()

# Close subprocess' file descriptors.
process.stdout.close()
process.stderr.close()

print "Waiting for process to exit..."
returnCode = process.wait()

if returnCode != 0:
   raise subprocess.CalledProcessError(returnCode, command)

আমি কেবল এটি ভাগ করে নিতে চেয়েছিলাম, আমি এই প্রশ্নটি শেষ করে অনুরূপ কিছু করার চেষ্টা করেছিলাম, তবে উত্তরগুলির কোনওোটাই আমার সমস্যার সমাধান করেনি। আশা করি এটি কাউকে সাহায্য করবে!

মনে রাখবেন যে আমার ব্যবহারের ক্ষেত্রে, একটি বাহ্যিক প্রক্রিয়া আমাদের যে প্রক্রিয়াটিকে হত্যা করে Popen()


1
পাইথন 2 এর জন্য আমাকে প্রায় ঠিক এর মতো কিছু ব্যবহার করতে হয়েছিল। পাইথন 2 তে এর মতো কিছু সরবরাহ করা উচিত ছিল, তবে এটি এর মতো কিছু একেবারে ঠিক নয়।
স্টুয়ার্ট অ্যাকসন

3

পাইথন স্ক্রিপ্ট থেকে stdout পেতে এই প্রশ্নের উত্তরগুলির জন্য যে কেউ চেষ্টা করছেন তার জন্য নোট করুন যে পাইথন তার স্টাডাউটটিকে বাফার করে এবং তাই স্টাডআউটটি দেখতে কিছুটা সময় নিতে পারে।

লক্ষ্য স্ক্রিপ্টে প্রতিটি স্টডআউট লেখার পরে নিম্নলিখিতটি যুক্ত করে এটি সংশোধন করা যেতে পারে:

sys.stdout.flush()

1
তবে পাইথনকে উপকীর্তি হিসাবে পাইথন চালানো প্রথম স্থানে উন্মাদ। আপনার স্ক্রিপ্টটি কেবল importঅন্য স্ক্রিপ্টের উচিত ; দেখব multiprocessingবা threadingআপনি parallelized সঞ্চালনের প্রয়োজন হলে।
ট্রিপলি

3
@ ট্রিপলি একাধিক পরিস্থিতি রয়েছে যেখানে পাইথনের উপকণ্ঠ হিসাবে পাইথন চালানো উপযুক্ত। আমার বেশ কয়েকটি পাইথন ব্যাচের স্ক্রিপ্ট রয়েছে যা আমি প্রতিদিনের ক্রমানুসারে চালাতে চাই। এগুলি মাস্টার পাইথন স্ক্রিপ্ট দ্বারা অর্কেস্টেট করা যেতে পারে যা কার্যকরকরণের সূচনা করে এবং চাইল্ড স্ক্রিপ্ট ব্যর্থ হলে আমাকে ইমেল করে। প্রতিটি স্ক্রিপ্ট অন্য থেকে স্যান্ডবক্সযুক্ত - নামকরণের বিরোধ নেই। আমি সমান্তরাল করছি না তাই বহু-প্রসেসিং এবং থ্রেডিং প্রাসঙ্গিক নয়।
ব্যবহারকারী 1379351

মূল অজগর প্রোগ্রামটি যেমন চালাচ্ছে তার চেয়ে আলাদা পাইথন এক্সিকিউটেবল ব্যবহার করে আপনি অন্যান্য অজগর প্রোগ্রামটিও শুরু করতে পারেন,subprocess.run("/path/to/python/executable", "pythonProgramToRun.py")
কাইল ব্রাইডেনস্টাইন

3

পাইথন> = 3.5 এ subprocess.runআমার জন্য কাজ করে :

import subprocess

cmd = 'echo foo; sleep 1; echo foo; sleep 2; echo foo'
subprocess.run(cmd, shell=True)

(এক্সিকিউশন চলাকালীন আউটপুট পাওয়াও ছাড়াই কাজ করে shell=True) https://docs.python.org/3/library/subprocess.html#subprocess.run


2
এটি "ফাঁসির সময়" নয়। subprocess.run()কল শুধুমাত্র ফেরৎ যখন subprocess সমাপ্ত চলমান রয়েছে।
ট্রিপলি

1
আপনি কীভাবে ব্যাখ্যা করতে পারেন যে এটি "মৃত্যুর সময়" যখন হয় না? এর মতো কিছু >>> import subprocess; subprocess.run('top')"প্রয়োগের সময়" মুদ্রণ করাও মনে হয় (এবং শীর্ষে কখনও শেষ হয় না)। আমি কিছু সূক্ষ্ম পার্থক্য উপলব্ধি না?
ব্যবহারকারী 7017793

যদি আপনি পাইপথনে আউটপুটটিকে পুনঃনির্দেশ করেন তবে আপনার সাথে stdout=subprocess.PIPEএটি topশেষ হওয়ার পরেই পড়তে পারে । আপনার পাইথন প্রোগ্রামটি সাবপ্রসেসটি কার্যকর করার সময় অবরুদ্ধ করা হয়েছে।
ট্রিপলি

1
ঠিক আছে, এটা বোঝা যায়। runপদ্ধতি এখনো কাজ করে আপনি শুধুমাত্র আগ্রহী হন এইজন্য আউটপুট যেমন উত্পন্ন হচ্ছে। অজস্রভাবে আপনি পাইথনের আউটপুট দিয়ে কিছু করতে চাইলে আপনি ঠিক বলেছেন যে এটি কাজ করে না।
ব্যবহারকারী 7017793

3

মূল প্রশ্নের উত্তর দেওয়ার জন্য, সেরা উপায় আইএমও কেবলমাত্র stdoutআপনার প্রোগ্রামের সাব-প্রসেসকে সরাসরি পুনঃনির্দেশ করছে stdout( allyচ্ছিকভাবে stderr, নীচের উদাহরণ হিসাবে যেমনটি করা যেতে পারে )

p = Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
p.communicate()

3
কম কোড সহ একই জিনিস জন্য কিছুই নির্দিষ্ট করে না stdoutএবং stderrনা। যদিও আমি মনে করি সুস্পষ্ট বর্ণনামূলক চেয়ে ভাল than
ট্রিপলি

1

এই পিওসি ক্রমাগত কোনও প্রক্রিয়া থেকে আউটপুট পড়ে এবং প্রয়োজনে অ্যাক্সেস করা যায়। শুধুমাত্র শেষ ফলাফল রাখা হয়, অন্যান্য সমস্ত আউটপুট বাতিল করা হয়, তাই পিআইপিই মেমরি থেকে বেরিয়ে আসা থেকে বাধা দেয়:

import subprocess
import time
import threading
import Queue


class FlushPipe(object):
    def __init__(self):
        self.command = ['python', './print_date.py']
        self.process = None
        self.process_output = Queue.LifoQueue(0)
        self.capture_output = threading.Thread(target=self.output_reader)

    def output_reader(self):
        for line in iter(self.process.stdout.readline, b''):
            self.process_output.put_nowait(line)

    def start_process(self):
        self.process = subprocess.Popen(self.command,
                                        stdout=subprocess.PIPE)
        self.capture_output.start()

    def get_output_for_processing(self):
        line = self.process_output.get()
        print ">>>" + line


if __name__ == "__main__":
    flush_pipe = FlushPipe()
    flush_pipe.start_process()

    now = time.time()
    while time.time() - now < 10:
        flush_pipe.get_output_for_processing()
        time.sleep(2.5)

    flush_pipe.capture_output.join(timeout=0.001)
    flush_pipe.process.kill()

print_date.py

#!/usr/bin/env python
import time

if __name__ == "__main__":
    while True:
        print str(time.time())
        time.sleep(0.01)

আউটপুট: আপনি স্পষ্ট দেখতে পাচ্ছেন যে কেবলমাত্র 2.5 ডলারের মধ্যবর্তী ব্যবধানে আউটপুট কিছুই নেই।

>>>1520535158.51
>>>1520535161.01
>>>1520535163.51
>>>1520535166.01

0

এটি কমপক্ষে পাইথন 3.4 এ কাজ করে

import subprocess

process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE)
for line in process.stdout:
    print(line.decode().strip())

1
প্রক্রিয়াটি শেষ না হওয়া পর্যন্ত এটি লুপটিতে অবরুদ্ধ রয়েছে এমন সমস্যা রয়েছে।
ট্রিপল

0

এখানে উত্তরগুলির মধ্যে কোনওটিই আমার সমস্ত প্রয়োজনকে সম্বোধন করে না।

  1. স্টাডাউটের জন্য কোনও থ্রেড নেই (কোনও মূল্য নেই, ইত্যাদি)
  2. আমার অন্যান্য চলমান জিনিসগুলি পরীক্ষা করার প্রয়োজন হিসাবে নন-ব্লক করা
  3. আমার একাধিক জিনিস যেমন স্ট্রিম আউটপুট করা দরকার ছিল তেমন পাইপ ব্যবহার করুন, লগ ফাইলে লিখুন এবং আউটপুটটির স্ট্রিং কপি ফিরিয়ে দিন।

সামান্য ব্যাকগ্রাউন্ড: আমি থ্রেডপুলএক্সিকিউটরটি একটি থ্রেডের পুল পরিচালনা করতে ব্যবহার করছি, প্রত্যেকটি একটি উপ-প্রসেস চালু করে এবং সেগুলি একযোগে চালাচ্ছি। (পাইথন 2.7 এ, তবে এটি আরও নতুন 3.x তেও কাজ করা উচিত)। আমি কেবল আউটপুট সংগ্রহের জন্য থ্রেডগুলি ব্যবহার করতে চাই না কারণ আমি অন্যান্য জিনিসের জন্য যতটা সম্ভব উপলভ্য চাই (২০ টি প্রক্রিয়ার একটি পুল চলতে চলতে 40 টি থ্রেড ব্যবহার করবে; প্রক্রিয়া থ্রেডের জন্য 1 এবং স্টাডাউটের জন্য 1 ... এবং আপনি যদি স্ট্যাডার চান তবে আরও অনেক কিছু)

আমি প্রচুর ব্যতিক্রম এবং এখান থেকে পিছনে চলেছি তাই এটি প্রযোজনার কোডের উপর ভিত্তি করে। আশা করি আমি কপি এবং পেস্ট এ এটি নষ্ট করিনি। এছাড়াও, প্রতিক্রিয়া অনেক স্বাগত!

import time
import fcntl
import subprocess
import time

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

# Make stdout non-blocking when using read/readline
proc_stdout = proc.stdout
fl = fcntl.fcntl(proc_stdout, fcntl.F_GETFL)
fcntl.fcntl(proc_stdout, fcntl.F_SETFL, fl | os.O_NONBLOCK)

def handle_stdout(proc_stream, my_buffer, echo_streams=True, log_file=None):
    """A little inline function to handle the stdout business. """
    # fcntl makes readline non-blocking so it raises an IOError when empty
    try:
        for s in iter(proc_stream.readline, ''):   # replace '' with b'' for Python 3
            my_buffer.append(s)

            if echo_streams:
                sys.stdout.write(s)

            if log_file:
                log_file.write(s)
    except IOError:
        pass

# The main loop while subprocess is running
stdout_parts = []
while proc.poll() is None:
    handle_stdout(proc_stdout, stdout_parts)

    # ...Check for other things here...
    # For example, check a multiprocessor.Value('b') to proc.kill()

    time.sleep(0.01)

# Not sure if this is needed, but run it again just to be sure we got it all?
handle_stdout(proc_stdout, stdout_parts)

stdout_str = "".join(stdout_parts)  # Just to demo

আমি নিশ্চিত এখানে ওভারহেড যুক্ত হচ্ছে তবে এটি আমার ক্ষেত্রে উদ্বেগের বিষয় নয়। কার্যত এটি আমার যা প্রয়োজন তা করে। কেবলমাত্র আমি সমাধান করি নি যে এটি লগ বার্তাগুলির জন্য নিখুঁতভাবে কাজ করে তবে আমি কিছু printবার্তা পরে এবং সমস্ত একবারে প্রদর্শিত হতে দেখি see


-2

পাইথন ৩.6 এ আমি এটি ব্যবহার করেছি:

import subprocess

cmd = "command"
output = subprocess.call(cmd, shell=True)
print(process)

1
এটি এই বিশেষ প্রশ্নের উত্তর নয়। সাব-প্রসেসটি তার আউটপুট পাওয়ার আগে শেষ হওয়ার জন্য অপেক্ষা করা নির্দিষ্টভাবে এবং স্পষ্টভাবে যা ওপি এড়াতে চেষ্টা করছে is পুরানো উত্তরাধিকার subprocess.call()ফাংশনটিতে কিছু ওয়ার্ট রয়েছে যা আরও নতুন ফাংশন দ্বারা স্থির করা হয়; পাইথন ৩.6 এ আপনি সাধারণত এটির subprocess.run()জন্য ব্যবহার করতে পারেন ; সুবিধার জন্য, পুরানো মোড়ক ফাংশনটি subprocess.check_output()এখনও উপলব্ধ - এটি প্রক্রিয়া থেকে আসল আউটপুট ফেরত দেয় (এই কোডটি কেবল প্রস্থান কোডটি ফিরিয়ে আনবে তবে তার পরিবর্তে অপরিবর্তিত কিছু মুদ্রণ করবে)।
ট্রিপলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.