python - লাইন দ্বারা subprocess stdout লাইন পড়ুন



(7)

বিট দেরিতে দেরী করে, কিন্তু আমার মনে হয় না যে এখানে সবচেয়ে সরল সমাধান কি না দেখে অবাক হয়ে গেল।

import io
import subprocess

proc = subprocess.Popen(["prog", "arg"], stdout=subprocess.PIPE)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):  # or another encoding
    # do something with line

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

#fake_utility.py, just generates lots of output over time
import time
i = 0
while True:
   print hex(i)*512
   i += 1
   time.sleep(0.5)

#filters output
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
for line in proc.stdout:
   #the real code does filtering here
   print "test:", line.rstrip()

আমি যে আচরণটি চাই তা হল ফিল্টার স্ক্রিপ্টের জন্য প্রতিটি লাইনটি সাবপ্রোকেস থেকে প্রাপ্ত হিসাবে মুদ্রণ করা। Sorta কি tee না কিন্তু পাইথন কোড সঙ্গে।

আমি কি অনুপস্থিত? এটা কি সম্ভব?

হালনাগাদ:

যদি sys.stdout.flush() একটি sys.stdout.flush() যোগ করা হয়, তবে পাইথন 3.1 এ কোডটিতে পছন্দসই আচরণ রয়েছে। আমি পাইথন 2.6 ব্যবহার করছি। আপনি মনে করেন যে proc.stdout.xreadlines() ব্যবহার করে proc.stdout.xreadlines() মতো কাজ করবে, কিন্তু এটি না।

আপডেট 2:

এখানে সংক্ষিপ্ত কাজ কোড।

#fake_utility.py, just generates lots of output over time
import sys, time
for i in range(10):
   print i
   sys.stdout.flush()
   time.sleep(0.5)

#display out put line by line
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
#works in python 3.0+
#for line in proc.stdout:
for line in iter(proc.stdout.readline,''):
   print line.rstrip()

প্রকৃতপক্ষে, আপনি যদি iterator সাজানো তারপর বাফারিং এখন আপনার সমস্যা হতে পারে। আপনি সাব-প্রসেসে পাইথনটিকে তার আউটপুট বাফার করতে বলতে পারেন।

proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)

হয়ে

proc = subprocess.Popen(['python','-u', 'fake_utility.py'],stdout=subprocess.PIPE)

Python মধ্যে থেকে পাইথন কল যখন আমি এই প্রয়োজন।


আমি পাইথনের সাথে শেষ for line in proc.stdout কাজ করেছি, কিন্তু আমি মনে করি সমস্যাটি for line in proc.stdout বিবৃতির সাথে for line in proc.stdout , যা এটির উপর পুনরাবৃত্তি করার আগে সমগ্র ইনপুটটি পড়ে। সমাধান পরিবর্তে readline() ব্যবহার করা হয়:

#filters output
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
while True:
  line = proc.stdout.readline()
  if line != '':
    #the real code does filtering here
    print "test:", line.rstrip()
  else:
    break

অবশ্যই আপনি এখনও subprocess 'বাফারিং মোকাবেলা করতে হবে।

দ্রষ্টব্য: ডকুমেন্টেশনের মতে, একটি ইটারারটারের সমাধানটি পঠনযোগ্য বাফার ব্যতীত, readline() ব্যবহার করা সমতুল্য হওয়া উচিত, তবে (বা ঠিক এই কারণে) প্রস্তাবিত পরিবর্তনটি আমার জন্য বিভিন্ন ফলাফল তৈরি করেছে (উইন্ডোজগুলিতে পাইথন 2.5 এক্সপি)।


রুমুলোর উত্তরের নিম্নলিখিত পরিবর্তনটি পাইথন ২ এবং 3 (2.7.1২ এবং 3.6.1) সম্পর্কে আমার জন্য কাজ করে:

import os
import subprocess

process = subprocess.Popen(command, stdout=subprocess.PIPE)
while True:
  line = process.stdout.readline()
  if line != '':
    os.write(1, line)
  else:
    break

আপনি লাইন w / o লুপ পড়তে পারেন। Python3.6 কাজ করে।

import os
import subprocess

process = subprocess.Popen(command, stdout=subprocess.PIPE)
list_of_byte_strings = process.stdout.readlines()

আপনি এই অতিরিক্ত পরামিতি subprocess.Popen পাস করতে চান। subprocess.Popen :

bufsize=1, universal_newlines=True

তারপর আপনি আপনার উদাহরণ হিসাবে পুনরাবৃত্তি করতে পারেন। (পাইথন 3.5 দিয়ে পরীক্ষা করা)


subprocess.open: http://docs.python.org/2/library/subprocess.html#subprocess.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)

আপনি যদি পপেন প্রাথমিকীকরণেও স্ট্যান্ডার্ড ত্রুটিটি পড়তে চান তবে আপনি 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()




python subprocess