วิธีใช้คำสั่ง 'subprocess' กับไพพ์


246

ฉันต้องการที่จะใช้กับsubprocess.check_output() ps -A | grep 'process_name'ฉันลองใช้วิธีแก้ไขปัญหาต่าง ๆ แต่ก็ยังไม่มีอะไรทำงาน ใครช่วยแนะนำฉันให้ทำอย่างไร



4
มีpsutilที่ช่วยให้ได้รับข้อมูลกระบวนการในลักษณะพกพา
jfs

คำตอบ:


439

หากต้องการใช้ท่อที่มีโมดูลที่คุณต้องผ่านsubprocessshell=True

อย่างไรก็ตามนี่ไม่แนะนำให้เลือกด้วยเหตุผลหลายประการไม่น้อยกว่านั้นคือความปลอดภัย ให้สร้างpsและgrepประมวลผลแยกจากกันและไพพ์เอาต์พุตจากหนึ่งไปอีกอันแทนดังนี้:

ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait()

อย่างไรก็ตามในกรณีเฉพาะของคุณวิธีแก้ปัญหาอย่างง่าย ๆ ก็คือการโทรsubprocess.check_output(('ps', '-A'))แล้วstr.findส่งสัญญาณออก


81
+1 สำหรับการแยกเอาต์พุต / อินพุตเพื่อหลีกเลี่ยงการใช้shell=True
Nicolas

5
อย่าลืมข้อผิดพลาดsubprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1เพียงหมายความว่า grep ไม่พบสิ่งใดดังนั้นจึงเป็นพฤติกรรมปกติ
Serge

2
ทำไมเราต้องใช้ps.wait()เมื่อเรามีเอาต์พุตอยู่แล้ว ps.wait.__doc__รอให้เด็กเลิก แต่เนื้อหาของเด็กดูเหมือนอยู่ในoutputตัวแปรแล้ว
Papouche Guinslyzinho

3
@MakisH คุณกำลังมองหาที่string.findซึ่งได้รับการคัดค้านในความโปรดปรานของstr.find(เช่นวิธีการfindเกี่ยวกับstrวัตถุ)
Taymon

4
หมายเหตุ: หากgrepตายก่อนกำหนด; psอาจแฮงค์ไปเรื่อย ๆ ถ้ามันสร้างผลผลิตเพียงพอที่จะเติมบัฟเฟอร์ท่อของ OS (เพราะคุณไม่ได้เรียกps.stdout.close()ในผู้ปกครอง) สลับลำดับเริ่มต้นเพื่อหลีกเลี่ยง
jfs

54

หรือคุณสามารถใช้วิธีการสื่อสารกับวัตถุ subprocess

cmd = "ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

วิธีการสื่อสารจะคืนค่า tuple ของเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐาน


3
ผมคิดว่าการใช้จะดีกว่าcommunicate มีคำเตือนดังกล่าว: "สิ่งนี้จะหยุดชะงักเมื่อใช้ stdout = PIPE และ / หรือ stderr = PIPE และกระบวนการลูกสร้างเอาต์พุตเพียงพอไปยังไพพ์เช่นที่บล็อกรอบัฟเฟอร์ไพพ์ของระบบปฏิบัติการเพื่อรับข้อมูลเพิ่มเติมใช้การสื่อสาร () เพื่อ หลีกเลี่ยงสิ่งนั้น " wait
เปาโล

2
เพื่อชี้แจงความคิดเห็นของเปาโลด้านบนคำเตือนสำหรับการรอไม่ใช่เพื่อการสื่อสาร - นั่นคือเหตุผลที่เขาบอกว่าการสื่อสารดีกว่า
EnemyBagJones

23

ดูเอกสารประกอบเกี่ยวกับการตั้งค่าไปป์ไลน์โดยใช้กระบวนการย่อย: http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline

ฉันยังไม่ได้ทดสอบตัวอย่างโค้ดต่อไปนี้ แต่ควรเป็นอย่างที่คุณต้องการ:

query = "process_name"
ps_process = Popen(["ps", "-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close()  # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0]

2
เมื่อตรวจสอบสิ่งนี้ล้มเหลวให้ดูคำตอบด้านล่างโดย Taymon สำหรับสิ่งที่ใช้งานได้โดยไม่ต้องล้อเล่น
Alvin

2
subprocess.check_output ไม่ปรากฏว่ามีอยู่ใน Python 2.6.9
RightmireM

6

วิธีแก้ปัญหาของ JKALAVIS นั้นดี แต่ฉันจะเพิ่มการปรับปรุงเพื่อใช้ shlex แทน SHELL = TRUE ด้านล่างฉัน grepping out เวลาค้นหา

#!/bin/python
import subprocess
import shlex

cmd = "dig @8.8.4.4 +notcp www.google.com|grep 'Query'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

1
ทำไม shellx บนเปลือก?
AFP_555

2
shlex ใช้ที่นี่ที่ไหน?
3lokh

4

ลองใช้'pgrep'คำสั่งแทน'ps -A | grep 'process_name'


2
ถ้าคุณต้องการรับ id กระบวนการชัดเจน
Shooe


-1

หลังจากPython 3.5คุณสามารถใช้:

    import subprocess

    f = open('test.txt', 'w')
    process = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE, universal_newlines=True)
    f.write(process.stdout)
    f.close()

การดำเนินการของคำสั่งจะถูกสกัดกั้นและการส่งออกจะอยู่ในprocess.stdout

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.