كيفية الحصول على الإخراج من الأوامر الخارجية تتحد مع الأنابيب

StackOverflow https://stackoverflow.com/questions/1404693

  •  05-07-2019
  •  | 
  •  

سؤال

ولقد أمر مثل هذا.

wmctrl -lp | awk '/gedit/ { print $1 }'

وأريد انتاجها داخل النصي الثعبان، حاولت هذا الرمز

>>> import subprocess
>>> proc =  subprocess.Popen(["wmctrl -lp", "|","awk '/gedit/ {print $1}"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.stdout.readline()
'0x0160001b -1 6504   beer-laptop x-nautilus-desktop\n'
>>> proc.stdout.readline()
'0x0352f117  0 6963   beer-laptop How to get output from external command combine with Pipe - Stack Overflow - Chromium\n'
>>> proc.stdout.readline()
'0x01400003 -1 6503   beer-laptop Bottom Expanded Edge Panel\n'
>>> 

ويبدو قانون بلدي هو الخطأ كان فقط wmctrl -lp تنفيذ، ويتم حذف | awk '{print $1}' صوري نتوقع ان انتاج مثل 0x03800081

$ wmctrl -lp | awk '/gedit/ {print $1}'
0x03800081

هل واحدة من فضلك مساعدة.

هل كانت مفيدة؟

المحلول

ومع shell=True، يجب عليك استخدام سطر الأوامر واحد بدلا من مجموعة، وإلا يتم تفسير حجج إضافية بك كوسائط قذيفة. من subprocess :

<اقتباس فقرة>   

في يونكس، مع شركة شل = صحيح: إذا سائط عبارة عن سلسلة، وهي تحدد سلسلة الأوامر لتنفيذ من خلال وعاء. إذا سائط هو تسلسل، يحدد البند الأول في سلسلة الأوامر، وسيتم التعامل مع أي بنود إضافية كوسائط قذيفة إضافية.

وهكذا ينبغي أن تكون مكالمتك:

subprocess.Popen("wmctrl -lp | sed /gedit/ '{print $1}'", shell=True, ...

وأعتقد أنك قد يكون لها أيضا اقتباسا واحد غير متوازن في هناك.

نصائح أخرى

ولأن يتم تمرير سلسلة في للبرنامج، فإنه يعتقد أن الأنبوب هو حجة إلى wmcrtrl، كما لو فعلتم

wmctrl -lp "|"

ووبالتالي الأنابيب الفعلي <م> تشغيل تضيع.

يجب مما يجعلها سلسلة واحدة تعطيك الواقع النتيجة الصحيحة:

>>> import subprocess as s
>>> proc = s.Popen("echo hello | grep e", shell=True, stdout=s.PIPE, stderr=s.PIPE)
>>> proc.stdout.readline()
'hello\n'
>>> proc.stdout.readline()
''

وبعد بعض البحوث، لدي البرمجية التالية التي تعمل بشكل جيد للغاية بالنسبة لي. فإنه يطبع في الأساس على حد سواء المعياري وستدير في الوقت الحقيقي. آمل أن يساعد شخص آخر الذي يحتاج إليه.

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result

عند الحاجة، وأعتقد أنه من السهل جمع الإخراج أو خطأ في سلسلة والعودة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top