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




(5)

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

#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()

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

bufsize=1, universal_newlines=True

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


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

import os
import subprocess

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

আমি পাইথনের সাথে শেষ 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 এক্সপি)।


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

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

হয়ে

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

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


রুমুলোর উত্তরের নিম্নলিখিত পরিবর্তনটি পাইথন ২ এবং 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




subprocess