เรียกใช้คำสั่งภายนอกใน Python

freshWoWer 08/19/2017. 30 answers, 2.045.096 views
python shell command subprocess external

ฉันสามารถเรียกใช้คำสั่งภายนอก (เช่นถ้าฉันพิมพ์ที่ shell Unix หรือคำสั่ง Windows) จากภายในสคริปต์ Python?

2 Comments
Triton Man 03/19/2015
นี่เป็นคำแนะนำที่ดีเกี่ยวกับการรวม python กับ shell: dreamyssoft.com/python-scriptorial-tutorial/shell-tutorial.php
6 J.F. Sebastian 06/12/2015
@TritonMan: ไม่ใช่บทแนะนำที่ดี ใช้ for line in proc.stdout: (หรือ for line in iter(proc.stdout.readline, '') ใน Python 2) แทน (moronic) for line in proc.stdout.readlines(): ดู Python: อ่านสตรีมข้อมูลจาก subprocess.communicate ()

30 Answers


David Cournapeau 02/14/2017.

ดู โมดูล subprocess ในไลบรารีมาตรฐาน:

from subprocess import call
call(["ls", "-l"]) 

ประโยชน์ของ subprocess vs system คือว่ามีความยืดหยุ่นมากขึ้น (คุณจะได้รับ stdout, stderr, รหัสสถานะ "จริง", จัดการข้อผิดพลาดที่ดีขึ้น ฯลฯ .. )

เอกสารอย่างเป็นทางการ แนะนำให้ใช้โมดูล subprocess มากกว่า os.system อื่น ():

โมดูล subprocess ให้สิ่งอำนวยความสะดวกที่มีประสิทธิภาพมากขึ้นสำหรับการพลิกโฉมกระบวนการใหม่ ๆ และเรียกค้นผลลัพธ์ของพวกเขา การใช้โมดูลนั้นดีกว่าการใช้ฟังก์ชั่นนี้ [ os.system() ]

" การแทนที่ฟังก์ชันเก่ากับโมดูลย่อยโพรเซส " ในเอกสาร subprocess อาจมีสูตรที่เป็นประโยชน์บางอย่าง

เอกสารอย่างเป็นทางการในโมดูล subprocess :

5 comments
155 nosklo 05/26/2009
ไม่เห็นสาเหตุที่คุณต้องการใช้ os.system แม้ในกรณีที่รวดเร็ว / สกปรก / เพียงครั้งเดียว กระบวนการย่อยดูเหมือนดีขึ้นมาก
33 Liam 07/29/2010
ฉันเห็นด้วยอย่างสมบูรณ์ว่ากระบวนการย่อยจะดีกว่า ฉันเพียงแค่ต้องเขียนสคริปต์อย่างรวดเร็วเช่นนี้เพื่อให้ทำงานบนเซิร์ฟเวอร์เก่ากับ Python 2.3.4 ซึ่งไม่มีโมดูล subprocess.
50 daonb 03/21/2012
นี่คือ เอกสารย่อย
6 goldenmean 11/10/2013
โทร (.. ) ให้ฉันมีข้อผิดพลาดเกี่ยวกับ oython 2.7.6: Traceback (โทรล่าสุดล่าสุดล่าสุด): File "E: \ Ajit \ MyPython \ synonyms1.py" บรรทัดที่ 27 ใน <module> call ("dir") <br /> ไฟล์ "C: \ Python27 \ lib \ subprocess.py" บรรทัด 524 ในการเรียกกลับ Popen (* popenargs, ** kwargs) .wait () <br/> ไฟล์ "C: \ Python27 \ lib \ subprocess.py "บรรทัด 711 ใน init errread, errwrite) <br/> ไฟล์" C: \ Python27 \ lib \ subprocess.py ", บรรทัด 948 ใน _execute_child startupinfo) <br/> WindowsError: [ข้อผิดพลาด 2] ระบบไม่พบไฟล์ที่ระบุ
61 J.F. Sebastian 12/21/2013
@goldenmean: เดาของฉันไม่มี ls.exe บน Windows ลอง call("dir", shell=True)

Eli Courtwright 04/11/2016.

นี่คือบทสรุปของวิธีการเรียกโปรแกรมภายนอกและข้อดีและข้อเสียของแต่ละข้อ:

  1. os.system("some_command with args") จะส่งคำสั่งและอาร์กิวเมนต์ไปยังระบบของคุณ นี้เป็นสิ่งที่ดีเพราะคุณสามารถเรียกใช้คำสั่งหลายครั้งในลักษณะนี้และการตั้งค่าท่อและการเปลี่ยนเส้นทางการรับเข้า / ตัวอย่างเช่น:

    os.system("some_command < input_file | another_command > output_file") 

    อย่างไรก็ตามในขณะนี้สะดวกคุณต้องจัดการด้วยตนเอง escaping ของอักขระ shell เช่นช่องว่าง ฯลฯ ในทางกลับกันนี้ยังช่วยให้คุณสามารถเรียกใช้คำสั่งซึ่งเป็นเพียงคำสั่งเชลล์และโปรแกรมภายนอกไม่จริง ดู เอกสารประกอบ

  2. stream = os.popen("some_command with args") จะทำสิ่งเดียวกับ os.system เว้นแต่ว่าจะให้คุณเป็นเหมือนไฟล์ที่คุณสามารถใช้เพื่อเข้าอินพุต / เอาท์พุตมาตรฐานสำหรับกระบวนการนั้นได้ มี 3 รูปแบบอื่น ๆ ของ popen ที่จัดการ i / o แตกต่างกันเล็กน้อย ถ้าคุณผ่านทุกอย่างเป็นสตริงแล้วคำสั่งของคุณจะถูกส่งผ่านไปยังเปลือก; ถ้าคุณส่งพวกเขาเป็นรายการแล้วคุณไม่จำเป็นต้องกังวลเกี่ยวกับการหลบหนีอะไร ดู เอกสารประกอบ

  3. คลาส Popen ของโมดูล subprocess นี้มีวัตถุประสงค์เพื่อเป็นแทน os.popen แต่มีข้อเสียของการเป็นเล็กน้อยที่ซับซ้อนมากขึ้นโดยอาศัยอำนาจในการเป็นที่ครอบคลุมดังนั้น ตัวอย่างเช่นคุณจะพูดว่า:

    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read() 

    แทน:

    print os.popen("echo Hello World").read() 

    แต่มันเป็นสิ่งที่ดีที่จะมีตัวเลือกทั้งหมดที่มีในชั้นเอกภาพเดียวแทน 4 ฟังก์ชัน Popen ที่แตกต่างกัน ดู เอกสารประกอบ

  4. ฟังก์ชัน call จากโมดูล subprocess นี้เป็นพื้นเช่นเดียวกับชั้น Popen และใช้เวลาทั้งหมดของอาร์กิวเมนต์เดียวกัน แต่ก็รอจนกว่าคำสั่งจะเสร็จสมบูรณ์และให้รหัสที่ส่งกลับ ตัวอย่างเช่น:

    return_code = subprocess.call("echo Hello World", shell=True) 

    ดู เอกสารประกอบ

  5. ถ้าคุณใช้ Python 3.5 หรือใหม่กว่าคุณสามารถใช้ฟังก์ชัน subprocess.run ใหม่ซึ่งมีลักษณะเหมือนข้างต้น แต่มีความยืดหยุ่นมากขึ้นและส่งกลับอ็อบเจ็กต์ CompletedProcess เมื่อคำสั่งเสร็จสิ้นการรัน

  6. โมดูล os มีฟังก์ชัน fork / exec / spawn ทั้งหมดที่คุณต้องการในโปรแกรม C แต่ไม่แนะนำให้ใช้โดยตรง

โมดูล subprocess อาจเป็นสิ่งที่คุณใช้

สุดท้ายโปรดทราบว่าสำหรับวิธีการทั้งหมดที่คุณผ่านคำสั่งสุดท้ายที่จะดำเนินการโดยเปลือกเป็นสตริงและคุณมีความรับผิดชอบในการหนีมัน There are serious security implications หากส่วนใดส่วนหนึ่งของสตริงที่คุณส่งผ่านไม่สามารถเชื่อถือได้อย่างสมบูรณ์ ตัวอย่างเช่นหากผู้ใช้ป้อนบางส่วน / ส่วนใดก็ได้ของสตริง หากคุณไม่แน่ใจให้ใช้วิธีการเหล่านี้กับค่าคงที่ เพื่อให้คำแนะนำเกี่ยวกับความหมายของรหัสนี้:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read() 

และจินตนาการว่าผู้ใช้ป้อน "แม่ของฉันไม่รักฉัน & & rm-rf /"

5 comments
8 Casebash 05/16/2010
คุณไม่ได้พูดถึง โมดูลคำสั่ง
111 Eli Courtwright 05/16/2010
@Casebash: ฉันไม่ได้พูดถึงเรื่องนี้เนื่องจากเอกสารระบุว่า The subprocess module provides more powerful facilities for spawning new processes and retrieving their results. Using the subprocess module is preferable to using the commands module. The subprocess module provides more powerful facilities for spawning new processes and retrieving their results. Using the subprocess module is preferable to using the commands module. ฉันก็ไม่ได้กล่าวถึงโมดูล popen2 เพราะยังล้าสมัยและทั้งสองและโมดูล commands จะหายไปจริงใน Python 3.0 และภายหลัง แทนการแก้ไขคำตอบของฉันฉันจะให้ความคิดเห็นเหล่านี้เป็นวิธีที่โมดูลเหล่านี้จะกล่าวถึง
15 PhoebeB 11/15/2010
บทความ ดีๆ เกี่ยวกับการใช้กระบวนการย่อยที่นี่: doughellmann.com/PyMOTW/subprocess
11 jldupont 01/21/2012
โมดูลคำสั่งจะเลิกใช้แล้ว
13 simao 06/12/2012
ในหลายกรณีคุณไม่จำเป็นต้องสร้างอินสแตนซ์อ็อบเจ็กต์ Popen โดยตรงคุณสามารถใช้ subprocess.check_call และ subprocess.check_output

EmmEff 12/10/2016.

ฉันมักใช้:

import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait() 

คุณมีอิสระที่จะทำสิ่งที่คุณต้องการด้วยข้อมูล stdout ในท่อ ในความเป็นจริงคุณสามารถละเว้นพารามิเตอร์เหล่านั้นได้ ( stdout= และ stderr= ) และจะทำงานเหมือนกับ os.system()

5 comments
19 J.F. Sebastian 11/16/2012
.readlines() อ่านบรรทัด all ในครั้งเดียวเช่นบล็อกจนกว่ากระบวนการย่อยจะออก (ปิดปลายท่อ) หากต้องการอ่านแบบเรียลไทม์ (หากไม่มีปัญหาบัฟเฟอร์) คุณสามารถ: for line in iter(p.stdout.readline, ''): print line,
EmmEff 11/17/2012
คุณสามารถอธิบายสิ่งที่คุณหมายถึงได้โดย "ถ้าไม่มีปัญหาเกี่ยวกับบัฟเฟอร์"? หากบล็อกกระบวนการสกัดกั้นกระบวนการเรียกกระบวนการย่อยจะขัดขวาง เช่นเดียวกันอาจเกิดขึ้นกับตัวอย่างเดิมของฉันด้วย อะไรจะเกิดขึ้นกับการบัฟเฟอร์?
9 J.F. Sebastian 11/17/2012
กระบวนการย่อยอาจใช้ buffering ในโหมดไม่ p.stdout.readline() กำหนดบัฟเฟอร์บรรทัดดังนั้น p.stdout.readline() (note: no s ที่ท้าย) จะไม่เห็นข้อมูลใด ๆ จนกว่าเด็กจะเติมบัฟเฟอร์ ถ้าเด็กไม่ได้ผลิตข้อมูลจำนวนมากผลลัพธ์ที่เกิดขึ้นจะไม่อยู่ในเวลาจริง ดูเหตุผลที่สองใน คำถาม: ทำไมไม่ใช้ท่อ (popen ())? . วิธีแก้ปัญหาบางอย่างมี ไว้ในคำตอบนี้ (pexpect, pty, stdbuf)
2 J.F. Sebastian 04/10/2013
@Paul: หากโค้ดของคุณสร้างผลลัพธ์ที่ไม่คาดคิดคุณสามารถสร้าง ตัวอย่างรหัสที่สมบูรณ์แบบ ที่ทำให้เกิดปัญหาขึ้นและ โพสต์คำถาม นั้นเป็น คำถามใหม่ กล่าวถึงสิ่งที่คุณคาดหวังว่าจะเกิดขึ้นและจะเกิดอะไรขึ้นแทน
2 Paul 04/11/2013
สิทธิทั้งหมดเอาคำแนะนำของคุณ stackoverflow.com/questions/15945585/ ... thanks!

newtover 07/27/2017.

คำแนะนำบางประการเกี่ยวกับการแยกกระบวนการย่อยออกจากการเรียกเข้า (เริ่มต้นกระบวนการย่อยในเบื้องหลัง)

สมมติว่าคุณต้องการเริ่มต้นงานที่ยาวนานจากสคริปต์ CGI นั่นคือกระบวนการย่อยควรใช้งานได้นานกว่าการประมวลผล CGI-script

ตัวอย่างคลาสสิกจากเอกสารโมดูลย่อยคือ:

import subprocess
import sys

# some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess

# some more code here 

ความคิดที่นี่คือคุณไม่ต้องการรอในกระบวนการย่อยสาย 'จนกว่า longtask.py เสร็จสิ้น แต่ไม่ชัดเจนว่าเกิดอะไรขึ้นหลังจากบรรทัด 'รหัสอื่น ๆ ที่นี่' จากตัวอย่าง

แพลตฟอร์มเป้าหมายของฉันเป็น freebsd แต่การพัฒนาอยู่ใน Windows ดังนั้นฉันประสบปัญหาใน Windows แรก

ใน Windows (win xp) ขั้นตอนหลักจะไม่เสร็จสิ้นจนกว่า longtask.py จะเสร็จสิ้นการทำงาน ไม่ใช่สิ่งที่คุณต้องการในสคริปต์ CGI ปัญหาไม่ได้เฉพาะกับงูหลามในชุมชน PHP ปัญหาจะเหมือนกัน

การแก้ปัญหาคือการส่งผ่าน DETACHED_PROCESS การสร้างกระบวนการสร้างสถานะ ไปยังฟังก์ชัน CreateProcess ที่สร้างขึ้นใน Win API ถ้าคุณได้ติดตั้ง pywin32 คุณสามารถนำเข้า flag จากโมดูล win32process มิฉะนั้นคุณควรกำหนดเอง:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid 

/ * UPD 2015.10.27 @eryksun ในข้อคิดเห็นด้านล่างโน้ตว่าธงที่ถูกต้องหมายถึงคือ CREATE_NEW_CONSOLE (0x00000010) * /

เมื่อ freebsd เรามีปัญหาอื่น: เมื่อกระบวนการหลักเสร็จสิ้นก็เสร็จสิ้นกระบวนการเด็กด้วย และนั่นไม่ใช่สิ่งที่คุณต้องการใน CGI-script อย่างใดอย่างหนึ่ง การทดลองบางอย่างแสดงให้เห็นว่าปัญหาดูเหมือนจะอยู่ในการแชร์ sys.stdout และวิธีการแก้ปัญหาการทำงานมีดังต่อไปนี้:

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) 

ฉันไม่ได้ตรวจสอบรหัสบนแพลตฟอร์มอื่น ๆ และไม่ทราบสาเหตุของพฤติกรรมใน freebsd ถ้าใครรู้กรุณาแบ่งปันความคิดของคุณ Googling ในการเริ่มต้นกระบวนการพื้นหลังใน Python จะไม่ทำให้เกิดแสงน้อยลง

5 comments
maranas 04/09/2010
ขอบคุณสำหรับคำตอบ! ฉันสังเกตเห็น "มุมแหลม" กับการพัฒนาแอปพลิเคชัน py2exe ใน pydev + eclipse ฉันสามารถบอกได้ว่าสคริปต์หลักไม่ถูกแยกออกเนื่องจากหน้าต่างเอาต์พุตของเอิร์ ธ ไม่ได้สิ้นสุดลง แม้ว่าสคริปต์จะดำเนินการเสร็จสิ้น แต่ก็ยังรอการส่งคืน แต่เมื่อฉันพยายามรวบรวมเพื่อ py2exe executable พฤติกรรมคาดหวังเกิดขึ้น (ทำงานกระบวนการเป็น detached แล้วออกจาก) ฉันไม่แน่ใจ แต่ชื่อที่ปฏิบัติการไม่ได้อยู่ในรายการกระบวนการอีกต่อไป (os.system ("start *"), os.spawnl กับ os.P_DETACH, subprocs ฯลฯ )
Alexey Lebedev 04/16/2012
Windows gotcha: แม้ว่าฉันจะประมวลผลกระบวนการกับ DETACHED_PROCESS เมื่อฉันฆ่าภูต Python ของฉันพอร์ตทั้งหมดที่เปิดโดยจะไม่เป็นอิสระจนกว่ากระบวนการที่คลอดทั้งหมดจะสิ้นสุดลง WScript.Shell แก้ไขปัญหาทั้งหมดของฉัน ตัวอย่างที่นี่: pastebin.com/xGmuvwSx
1 eryksun 10/27/2015
ข้อผิดพลาดต่อไปนี้ไม่ถูกต้อง: "[o] n windows (win xp) ขั้นตอนหลักจะไม่เสร็จสิ้นจนกว่า longtask.py จะเสร็จสิ้นการทำงาน" แม่แบบจะออกจากปกติ แต่หน้าต่างคอนโซล (conhost.exe instance) จะปิดเมื่อกระบวนการที่แนบมาล่าสุดออกและเด็กอาจสืบทอดคอนโซลของผู้ปกครอง การตั้งค่า DETACHED_PROCESS ใน DETACHED_PROCESS จะหลีกเลี่ยงสิ่งนี้โดยป้องกันไม่ให้เด็กรับช่วงหรือสร้างคอนโซล ถ้าคุณต้องการคอนโซลใหม่แทนต้องการใช้ CREATE_NEW_CONSOLE (0x00000010)
1 eryksun 10/27/2015
ฉันไม่ได้หมายความว่าการดำเนินการตามกระบวนการแยกออกไม่ถูกต้อง ที่กล่าวว่าคุณอาจต้องตั้งมาตรฐานจัดการกับไฟล์ท่อหรือ os.devnull เนื่องจากบางโปรแกรมคอนโซลออกมีข้อผิดพลาดเป็นอย่างอื่น สร้างคอนโซลใหม่เมื่อคุณต้องการให้กระบวนการลูกโต้ตอบกับผู้ใช้พร้อมกับกระบวนการหลัก อาจทำให้เกิดความสับสนในการพยายามทำทั้งสองอย่างในหน้าต่างเดียว

sirwart 04/04/2014.

ฉันขอแนะนำให้ใช้โมดูลย่อยแทน os.system เพราะ shell ไม่ทำงานสำหรับคุณและปลอดภัยมาก: http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost']) 
2 comments
Joe Skora 09/18/2008
และกระบวนการย่อยจะช่วยให้คุณสามารถแนบไปกับอินพุต / เอาต์พุตสตรีมของกระบวนการ ฯลฯ
6 habnabit 09/18/2008
กระบวนการย่อยไม่ได้ทำ shell escaping สำหรับคุณเนื่องจากหลีกเลี่ยงการใช้เปลือกทั้งหมด ซึ่งหมายความว่าการเริ่มต้นทำงานเร็วขึ้นเล็กน้อยและมีค่าใช้จ่ายน้อยกว่า

Alexandra Franks 01/26/2016.
import os
cmd = 'ls -al'
os.system(cmd) 

ถ้าคุณต้องการส่งคืนผลลัพธ์ของคำสั่งคุณสามารถใช้ os.popen อย่างไรก็ตามนี่คือการคัดค้านตั้งแต่รุ่น 2.6 สำหรับ โปรโตคอลย่อย ซึ่งคำตอบอื่น ๆ ครอบคลุมได้ดี

3 comments
BuvinJ 04/12/2017
เพิ่ม cmd = subprocess.list2cmdline( [ 'my','list','of','tokens' ] ) เพื่อจัดการกับ escapes
Karlos 04/15/2017
การทำแผนที่แบบโอเพ่นด์ os แบบอัตโนมัติเมื่อทำงานในระบบสภาพแวดล้อมหลายระบบ

nimish 09/18/2008.
import os
os.system("your command") 

โปรดทราบว่าสิ่งนี้เป็นอันตรายเนื่องจากคำสั่งไม่ได้ทำความสะอาด ฉันปล่อยให้คุณถึง google สำหรับเอกสารที่เกี่ยวข้องในโมดูล 'os' และ 'sys' มีชุดของฟังก์ชัน (exec *, spawn *) ที่จะทำสิ่งที่คล้ายกัน


athanassis 05/28/2017.

ตรวจสอบไลบรารี Python ของ "pexpect" อีกด้วย

จะช่วยให้การควบคุมการโต้ตอบของโปรแกรมภายนอก / คำสั่งได้ ssh, ftp, telnet ฯลฯ คุณสามารถพิมพ์สิ่งที่ชอบ:

child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password') 

Jorge E. Cardona 07/23/2013.

ฉันมักจะใช้ fabric สำหรับสิ่งนี้เช่น:

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, ) 

แต่นี้ดูเหมือนจะเป็นเครื่องมือที่ดี: sh (Python subprocess interface)

ดูตัวอย่าง:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True) 
1 comments
2 Yauhen Yakimovich 05/23/2013
sh ดีกว่าโมดูล subprocess ช่วยให้สามารถรวมเปลือกได้ดีขึ้น

Facundo Casco 12/10/2016.

ถ้าสิ่งที่คุณต้องการคือผลลัพธ์จากคำสั่งที่คุณกำลังโทร
แล้วคุณสามารถใช้ subprocess.check_output (Python 2.7+)

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n' 

โปรดสังเกตพารามิเตอร์ shell

ถ้าเชลล์เป็น True คำสั่งที่ระบุจะถูกดำเนินการผ่านทางเชลล์ นี้จะมีประโยชน์ถ้าคุณใช้ Python เป็นหลักสำหรับการไหลของการควบคุมขั้นสูงที่จะนำเสนอผ่านเปลือกระบบส่วนใหญ่และยังคงต้องการความสะดวกในการเข้าถึงคุณสมบัติของเชลล์อื่น ๆ เช่นท่อเชลล์สัญลักษณ์แทนชื่อไฟล์การขยายตัวแปรสภาพแวดล้อมและการขยายตัวของ ~ ไปยังบ้านของผู้ใช้ ไดเรกทอรี อย่างไรก็ตามโปรดทราบว่า Python มีการนำคุณลักษณะต่างๆของ shell มาใช้ (โดยเฉพาะ glob , fnmatch , os.walk() , os.path.expandvars() , os.path.expanduser() และ shutil )


Usman Khan 10/28/2012.

นี่คือวิธีที่ฉันใช้คำสั่งของฉัน รหัสนี้มีทุกสิ่งที่คุณต้องการมากทีเดียว

from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip() 
3 comments
Eric 07/23/2013
การส่งคำสั่งเป็นสตริงเป็นความคิดที่ไม่ดี
1 Adam Matan 04/02/2014
ฉันคิดว่ามันเป็นที่ยอมรับสำหรับคำสั่งที่เข้ารหัสยากถ้ามันเพิ่มขึ้นอ่าน.
sam 09/12/2016
ขอบคุณ มาจาก Perl และ Ruby, Python เป็น PITA เมื่อพูดถึงการรันคำสั่ง อ่านโซลูชั่นมากมาย เช่นเดียวกับคุณด้วย popen

Honza Javorek 08/12/2016.

ด้วย Standard Library

ใช้ โมดูลย่อย :

from subprocess import call
call(['ls', '-l']) 

เป็นวิธีมาตรฐานที่แนะนำ อย่างไรก็ตามงานที่ซับซ้อนมากขึ้น (ท่อส่งออกการป้อนข้อมูล ฯลฯ ) อาจสร้างความยุ่งยากในการสร้างและเขียน

หมายเหตุ: shlex.split สามารถช่วยคุณในการแยกคำสั่งสำหรับการ call และฟังก์ชั่น subprocess อื่น ๆ ในกรณีที่คุณไม่ต้องการ (หรือคุณไม่สามารถ!) ให้พวกเขาในรูปแบบของรายการ:

import shlex
from subprocess import call
call(shlex.split('ls -l')) 

กับการพึ่งพาภายนอก

ถ้าคุณไม่ทราบ dependencies ภายนอกใช้ plumbum :

from plumbum.cmd import ifconfig
print(ifconfig['wlan0']()) 

เป็นกระดาษห่อกระดาษ subprocess ดีที่สุด เป็นแพลตฟอร์มข้ามแพลตฟอร์มนั่นคือทำงานได้ทั้งระบบ Windows และ Unix เหมือน ติดตั้งโดย pip install plumbum

อีกห้องสมุดที่เป็นที่นิยมคือ sh :

from sh import ifconfig
print(ifconfig('wlan0')) 

อย่างไรก็ตาม sh ลดการสนับสนุนของ Windows ดังนั้นจึงไม่น่ากลัวอย่างที่เคยเป็น ติดตั้งโดยการติดตั้ง pip install sh


Joe 05/23/2017.

ปรับปรุง:

subprocess.run เป็นวิธีที่แนะนำ ตั้งแต่งูหลาม 3.5 ถ้าโค้ดของคุณไม่จำเป็นต้องรักษาความเข้ากันได้กับเวอร์ชัน Python เวอร์ชันก่อนหน้า สอดคล้องกันมากขึ้นและมีความสะดวกในการใช้งานคล้ายกันเช่นเดียวกับ Envoy (ท่อไม่ใช่เรื่องง่ายๆ แต่ดู คำถามนี้ได้อย่างไร )

ต่อไปนี้เป็นตัวอย่างจาก เอกสาร

เรียกใช้กระบวนการ:

>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0) 

ยกเมื่อล้มเหลวทำงาน:

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 

จับภาพเอาต์พุต:

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n') 

คำตอบเดิม:

ผมขอแนะนำให้ลอง Envoy เป็น wrapper สำหรับ subprocess ซึ่งจะ มีจุดมุ่งหมายเพื่อแทนที่ โมดูลเก่าและหน้าที่ ผู้ส่งเป็นกระบวนการย่อยสำหรับมนุษย์

ตัวอย่างการใช้งานจาก readme :

>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
'' 

ท่อสิ่งรอบเกินไป:

>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[] 
2 comments
4 J.F. Sebastian 10/03/2015
หมายเหตุ: subprocess.run() ที่ละเว้นสถานะทางออกที่ไม่ใช่ศูนย์โดยค่าเริ่มต้นคือการถดถอยเมื่อเทียบกับ subprocess.check_call() หรือ subprocess.check_output() python -mthis : "ข้อผิดพลาดไม่ควรผ่านไปอย่างเงียบเชียบยกเว้นกรณีเงียบอย่างชัดเจน"
itirazimvar 09/01/2016
ขอบคุณคนส่งกำลังทำงานดีกว่ากระบวนการย่อยคุณช่วยชีวิตฉันได้ คำสั่งที่เป็นคำสั่ง = "ansible-playbook playbook.yaml --extra-vars = \" esxi_host = {0} extravar1 = {1} extravar2 = {2} extravar3 = {3} \ "" รูปแบบ (extravar1, extravar2 , extravar3) และ r.envoy.run (คำสั่ง)

Tom Fuller 05/28/2017.

มีห้องสมุดที่แตกต่างกันมากมายซึ่งอนุญาตให้คุณเรียกใช้คำสั่งภายนอกด้วย Python สำหรับแต่ละห้องสมุดฉันได้ให้คำอธิบายและแสดงตัวอย่างการเรียกใช้คำสั่งภายนอก คำสั่งที่ฉันใช้เป็นตัวอย่างคือ ls -l (แสดงไฟล์ทั้งหมด) ถ้าคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับไลบรารีใด ๆ ที่ฉันได้ระบุไว้และเชื่อมโยงเอกสารสำหรับแต่ละห้องสมุด

Sources:

These are all the libraries:

หวังว่านี้จะช่วยให้คุณตัดสินใจที่จะใช้ห้องสมุด :)

subprocess

Subprocess ช่วยให้คุณสามารถเรียกใช้คำสั่งภายนอกและเชื่อมต่อเข้ากับอินพุต / เอาต์พุต / ข้อผิดพลาดของท่อ (stdin, stdout และ stderr) กระบวนการย่อยเป็นตัวเลือกเริ่มต้นสำหรับการเรียกใช้คำสั่ง แต่บางครั้งโมดูลอื่น ๆ จะดีกว่า

subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command 

os

os ใช้สำหรับ "ฟังก์ชันการทำงานที่ขึ้นกับระบบปฏิบัติการ" นอกจากนี้ยังสามารถใช้เรียกคำสั่งภายนอกด้วย os.system และ os.popen (หมายเหตุ: นอกจากนี้ยังมี subprocess.popen) os จะเรียกใช้เชลล์และเป็นทางเลือกที่ง่ายสำหรับผู้ที่ไม่ต้องการหรือไม่ทราบวิธีใช้ subprocess.run

os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output 

sh

sh เป็นส่วนติดต่อย่อยซึ่งจะช่วยให้คุณสามารถเรียกใช้โปรแกรมได้เหมือนกับว่าเป็นฟังก์ชัน นี่เป็นประโยชน์ถ้าคุณต้องการเรียกใช้คำสั่งหลายครั้ง

sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function 

plumbum

plumbum เป็นไลบรารีสำหรับ "script-like" โปรแกรมไพ ธ อน คุณสามารถเรียกโปรแกรมเช่นฟังก์ชั่นเช่นเดียวกับใน sh Plumbum มีประโยชน์ถ้าคุณต้องการใช้ท่อโดยไม่มีเปลือก

ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command 

pexpect

pexpect ช่วยให้คุณสามารถวางไข่แอ็พพลิเคชันเด็กควบคุมและหารูปแบบในเอาท์พุทได้ นี่เป็นทางเลือกที่ดีกว่าสำหรับ subprocess สำหรับคำสั่งที่คาดว่าจะมี tty บน Unix

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword') 

fabric

ผ้าเป็นไลบรารีไพ ธ อน 2.5 และ 2.7 ช่วยให้คุณสามารถรันคำสั่งเชลล์ภายในและระยะไกลได้ ผ้าเป็นทางเลือกที่ง่ายสำหรับการรันคำสั่งในเชลล์ที่ปลอดภัย (SSH)

fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output 

envoy

ทูตเรียกว่า "กระบวนการย่อยสำหรับมนุษย์" ใช้เป็นกระดาษห่อหุ้มสะดวกรอบโมดูล subprocess

r = envoy.run("ls -l") # Run command
r.std_out # get output 

commands

commands มีฟังก์ชัน wrapper สำหรับ os.popen แต่ได้ถูกลบออกจาก Python 3 เนื่องจาก subprocess เป็นทางเลือกที่ดีกว่า

การแก้ไขขึ้นอยู่กับความคิดเห็นของ JF Sebastian

4 comments
Tom Fuller 10/29/2016
ฉันคิดถึงอะไรหรือ?
3 J.F. Sebastian 11/02/2016
อาจเป็นประโยชน์ในการระบุอย่างชัดเจน when และ why คุณต้องการห้องสมุดมากกว่าอีกเช่น pexpect มีประโยชน์สำหรับ คำสั่งที่คาดหวัง tty บน Unix plumbum สามารถใช้เพื่อ เรียกใช้ท่อได้โดยไม่ต้องเรียกเปลือกเปลือกตา fabric เป็นวิธีง่ายๆในการ รันคำสั่งผ่าน ssh, subprocess (ไม่เหมือนกับ os ) ไม่เคยรันเชลล์เว้นแต่คุณจะถาม - เป็นตัวเลือกเริ่มต้นสำหรับรันคำสั่งภายนอกบางครั้งคุณอาจต้องการ ทางเลือก
Tom Fuller 11/02/2016
ฉันได้แก้ไขคำตอบของฉันตามความคิดเห็นของคุณแล้ว :)
1 J.F. Sebastian 11/02/2016
os "คำสั่งภายนอก" ฟังก์ชันจะดำเนินการในแง่ของ subprocess ภายใน อาจเป็นประโยชน์สำหรับผู้ใช้จากภาษาอื่น ( system() , popen() เป็น API ทั่วไป) ที่ไม่ต้องการพลังเต็มของโมดูล subprocess และผู้ที่ไม่มีเวลาเรียนรู้วิธีใช้ subprocess.run() และ ฟังก์ชันย่อยอื่น ๆ '

Zuckonit 05/28/2017.

ไม่มีผลลัพธ์ของผลลัพธ์:

import os
os.system("your command here") 

ด้วยผลลัพธ์ของผลลัพธ์:

import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here") 
1 comments
2 Ramsharan 10/19/2013
ฉันชอบส่วนที่ with output of result ฉันต้องการนี้สำหรับใช้ในคอนโซลประเสริฐ

stuckintheshuck 10/10/2014.

นอกจากนี้ยังมี Plumbum

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand()
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns 
1 comments
J.F. Sebastian 07/13/2015
หรือเพิ่มบิตของเวทมนตร์: from plumbum.cmd import ls, grep; output = (ls | grep['pattern'])() from plumbum.cmd import ls, grep; output = (ls | grep['pattern'])()

Ben Hoffstein 11/02/2014.

https://docs.python.org/2/library/subprocess.html

... หรือสำหรับคำสั่งง่ายๆ:

import os
os.system('cat testfile') 

Martin W 12/10/2016.

os.system ไม่เป็นไร แต่เป็นวันที่ นอกจากนี้ยังไม่ปลอดภัยมาก ลองใช้ subprocess แทน subprocess ไม่ได้เรียก sh โดยตรงและดังนั้นจึงมีความปลอดภัยมากกว่า os.system

ดูข้อมูลเพิ่มเติม ที่นี่


William Keller 12/10/2016.

os.system ถูกแทนที่โดยโมดูล subprocess ใช้ subproccess แทน

3 comments
14 Michael Mior 03/29/2010
บางทีตัวอย่างของการใช้ subprocess ?
5 Mark Amery 12/22/2016
ระบุว่าคำตอบที่ได้รับการตอบได้แนะนำ subprocess ไว้ก่อนหน้านี้และมีรายละเอียดมากขึ้นฉันเห็นว่าไม่มีค่าสำหรับคำตอบนี้ที่เกาะติดกัน
sudo 04/23/2017
มีอะไรผิดปกติกับ os.system ? ใช้งานได้ง่ายที่สุดเพียงแค่เรียกใช้สิ่งที่คุณใส่ในสตริงและไม่ได้มีข้อแม้ทั้งหมดที่ผู้คนกำลังแสดงรายการตามคำตอบที่ยอมรับ

cdunn2001 01/18/2011.

subprocess.check_call สะดวกหากคุณไม่ต้องการทดสอบค่าที่ส่งคืน มันมีข้อยกเว้นข้อผิดพลาดใด ๆ


Atinc Delican 12/10/2016.

มีความแตกต่างที่นี่ซึ่งไม่ได้กล่าวถึงข้างต้น

subprocess.Popen จะประมวลผลเป็น subprocess ในกรณีของฉันฉันจำเป็นต้องเรียกใช้ไฟล์ที่ต้องการสื่อสารกับโปรแกรมอื่น

ฉันพยายามประมวลผลย่อยการดำเนินการสำเร็จ ไม่สามารถสื่อสารกับ w /. ทุกอย่างปกติเมื่อฉันทำงานทั้งจาก terminal

หนึ่งเพิ่มเติม: (หมายเหตุ: kwrite จะทำงานแตกต่างจากปพลิเคชันอื่น ๆ ถ้าคุณลองด้านล่างมีผล firefox จะไม่เหมือนกัน)

ถ้าคุณลอง os.system("kwrite") การไหลของโปรแกรมจะหยุดทำงานจนกว่าผู้ใช้จะปิดระบบ kwrite เพื่อเอาชนะที่ฉันพยายามแทน os.system(konsole -e kwrite) โปรแกรมเวลานี้ยังคงไหล แต่ kwrite กลายเป็นกระบวนการย่อยของ konsole

ทุกคนเรียก kwrite ไม่เป็นกระบวนการย่อย (เช่นที่ตรวจสอบระบบจะต้องปรากฏที่ขอบซ้ายสุดของต้นไม้)


Priyankara 05/28/2017.

ใช้:

import os

cmd = 'ls -al'

os.system(cmd) 

os - โมดูลนี้ให้วิธีแบบพกพาในการใช้ฟังก์ชันการทำงานที่ขึ้นกับระบบปฏิบัติการ

สำหรับฟังก์ชัน os เพิ่มเติม นี่ คือเอกสารประกอบ

3 comments
PolarisUser 10/09/2015
มีวิธีที่จะผลักดันผลของ cmd ไปยังแฟ้ม? ฉันม้วนเว็บไซต์และฉันต้องการให้ไปที่ไฟล์
user2820579 10/16/2015
นี่เป็นวิธีแก้ปัญหาที่ง่ายที่สุดและมีประสิทธิภาพ @PolarisUser คุณสามารถใช้คำสั่ง linux ทั่วไป: > outputfile.txt
Corey Goldberg 12/09/2015
นอกจากนี้ยังเลิกใช้ ใช้กระบวนการย่อย

Saurabh Bangad 06/11/2012.

os.system ไม่อนุญาตให้คุณเก็บผลลัพธ์ไว้ดังนั้นถ้าคุณต้องการเก็บผลลัพธ์ไว้ในรายการบางส่วนหรือสิ่งที่เรียกใช้งาน subprocess.call


Emil Stenström 04/30/2014.

ฉันมักจะใช้ กระบวนการย่อย ร่วมกับ shlex (เพื่อจัดการกับการหนีจากสตริงที่ยกมา):

>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params) 

houqp 05/01/2014.

ปลั๊กตัวตนฉันเขียนไลบรารีสำหรับ: P https://github.com/houqp/shell.py

มันเป็นพื้น wrapper สำหรับ popen และ shlex สำหรับตอนนี้ นอกจากนี้ยังสนับสนุนคำสั่งท่อเพื่อให้คุณสามารถคำสั่งลูกโซ่ได้ง่ายขึ้นใน Python ดังนั้นคุณสามารถทำสิ่งต่างๆได้เช่น:

ex('echo hello shell.py') | "awk '{print $2}'" 

admire 05/28/2017.

คุณสามารถใช้ Popen จากนั้นคุณสามารถตรวจสอบสถานะของกระบวนการ:

from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill() 

ตรวจสอบ subprocess.Popen


IRSHAD 07/20/2016.

เพื่อเรียกรหัสเครือข่ายจากนิวตรอน openstack:

#!/usr/bin/python
import os
netid= "nova net-list | awk '/ External / { print $2 }'"
temp=os.popen(netid).read()  /* here temp also contains new line (\n) */
networkId=temp.rstrip()
print(networkId) 

ผลลัพธ์ของ nova net-list

+--------------------------------------+------------+------+
| ID                                   | Label      | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1      | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External   | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal   | None |
+--------------------------------------+------------+------+ 

ผลลัพธ์ของการ print(networkId)

27a74fcd-37c0-4789-9414-9531b7e3f126 

yuval 11/27/2016.

ภายใต้ Linux ในกรณีที่คุณต้องการเรียกใช้คำสั่งภายนอกที่จะรันอย่างอิสระ (จะทำงานต่อหลังจากที่สคริปต์ Python ยุติลง) คุณสามารถใช้คิวง่ายๆเป็น ตัวจัดคิวงาน หรือคำสั่งที่

ตัวอย่างกับตัวจัดคิวงาน:

import os
os.system('ts ') 

หมายเหตุเกี่ยวกับ spool ( ts ):

  1. คุณสามารถกำหนดจำนวนของกระบวนการพร้อมกันที่จะเรียกใช้ ("ช่อง") ด้วย:

    ts -S

  2. การติดตั้ง ts ไม่จำเป็นต้องมีสิทธิ์ผู้ดูแลระบบ คุณสามารถดาวน์โหลดและเรียบเรียงได้จากแหล่งข้อมูลด้วยการสร้างแบบง่ายๆเพิ่มลงในเส้นทางของคุณและทำเสร็จแล้ว


urosjarc 05/28/2017.

นี่เป็นสองเซนต์ของฉัน: ในมุมมองของฉันนี่คือแนวทางปฏิบัติที่ดีที่สุดเมื่อจัดการกับคำสั่งภายนอก ...

นี่คือค่าที่ส่งคืนจากเมธอด execute ...

pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop") 

นี่คือวิธีดำเนินการ ...

def execute(cmdArray,workingDir):

    stdout = ''
    stderr = ''

    try:
        try:
            process = subprocess.Popen(cmdArray,cwd=workingDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
        except OSError:
            return [False, '', 'ERROR : command(' + ' '.join(cmdArray) + ') could not get executed!']

        for line in iter(process.stdout.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stdout += echoLine

        for line in iter(process.stderr.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stderr += echoLine

    except (KeyboardInterrupt,SystemExit) as err:
        return [False,'',str(err)]

    process.stdout.close()

    returnCode = process.wait()
    if returnCode != 0 or stderr != '':
        return [False, stdout, stderr]
    else:
        return [True, stdout, stderr] 
1 comments
ppperry 07/07/2016
ศักยภาพการหยุดชะงัก: ใช้เมธอด .communicate แทน

Swadhikar C 05/28/2017.

ใน Windows คุณสามารถนำเข้าโมดูล subprocess และเรียกใช้คำสั่งภายนอกได้โดยเรียก subprocess.Popen() , subprocess.Popen().communicate() และ subprocess.Popen().wait() ด้านล่าง:

# Python script to run a command line
import subprocess

def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    rc = process.wait()

    if rc != 0:
        print "Error: failed to execute command:", cmd
        print error
    return result
# def

command = "tasklist | grep python"
print "This process detail: \n", execute(command) 

เอาท์พุท:

This process detail:
python.exe                     604 RDP-Tcp#0                  4      5,660 K 

Related questions

Hot questions

Language

Popular Tags