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


4882

คุณเรียกคำสั่งภายนอกได้อย่างไร (ราวกับว่าฉันพิมพ์ที่ Unix shell หรือ Windows command prompt) จากภายในสคริปต์ Python

คำตอบ:


4693

ดูโมดูลย่อยในไลบรารีมาตรฐาน:

import subprocess
subprocess.run(["ls", "-l"])

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

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

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

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

สำหรับเวอร์ชันของ Python ก่อน 3.5 ให้ใช้call:

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

มีวิธีใช้การทดแทนตัวแปรหรือไม่? IE ฉันพยายามทำecho $PATHโดยใช้call(["echo", "$PATH"])แต่มันแค่สะท้อนสตริงตัวอักษร$PATHแทนที่จะทำการทดแทนใด ๆ ฉันรู้ว่าฉันสามารถรับตัวแปรสภาพแวดล้อม PATH ได้ แต่ฉันสงสัยว่ามีวิธีที่ง่ายในการให้คำสั่งทำงานอย่างถูกต้องเหมือนกับว่าฉันเรียกใช้งานด้วยการทุบตี
Kevin Wheeler

@KevinWheeler คุณจะต้องใช้shell=Trueเพื่อการทำงาน
SethMMorton

38
@KevinWheeler คุณไม่ควรใช้shell=Trueเพื่อจุดประสงค์นี้งูใหญ่มาพร้อมกับos.path.expandvars os.path.expandvars("$PATH")ในกรณีของคุณคุณสามารถเขียน: @SethMMorton โปรดพิจารณาความคิดเห็นของคุณอีกครั้ง -> ทำไมไม่ใช้ shell = True
Murmel

โทรบล็อกอะไร คือถ้าฉันต้องการเรียกใช้หลายคำสั่งในforวงฉันจะทำอย่างไรโดยไม่ได้บล็อกสคริปต์หลามของฉัน ฉันไม่สนใจเกี่ยวกับผลลัพธ์ของคำสั่งที่ฉันต้องการเรียกใช้จำนวนมาก
Charlie Parker

4
หากคุณต้องการสร้างรายการจากคำสั่งพร้อมพารามิเตอร์รายการที่สามารถใช้กับsubprocessเวลาshell=Falseได้จากนั้นใช้shlex.splitวิธีง่ายๆในการทำเอกสารนี้docs.python.org/2/library/shlex.html#shlex.split
Daniel F

2982

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

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

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

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

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

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

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

    แทน:

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

    แต่มันก็ดีที่มีตัวเลือกทั้งหมดในคลาสหนึ่งเดียวแทนฟังก์ชัน popen ที่แตกต่างกัน 4 ตัว ดูเอกสาร

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

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

    ดูเอกสาร

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

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

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

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

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

และจินตนาการว่าผู้ใช้ป้อนบางสิ่ง "แม่ของฉันไม่ได้รักฉัน && rm -rf /" ซึ่งสามารถลบระบบไฟล์ทั้งหมดได้


22
คำตอบ / คำอธิบายที่ดี คำตอบนี้แสดงให้เห็นถึงคำขวัญของงูใหญ่ที่อธิบายไว้ในบทความนี้อย่างไร fastcompany.com/3026446/… "Stylistically, Perl และ Python มีปรัชญาต่าง ๆ คำขวัญที่รู้จักกันดีของ Perl คือ" มีมากกว่าหนึ่งวิธีที่จะทำ "Python ได้รับการออกแบบให้มีวิธีที่ชัดเจนในการดำเนินการ" ดูเหมือนว่ามันควรจะเป็น วิธีอื่น ๆ ! ใน Perl ฉันรู้เพียงสองวิธีที่จะรันคำสั่ง - openใช้กลับเห็บหรือ
Jean

12
ถ้าใช้ Python 3.5 subprocess.run()ขึ้นไปใช้ docs.python.org/3.5/library/subprocess.html#subprocess.run
phoenix

4
สิ่งที่โดยทั่วไปต้องรู้คืออะไรจะทำอย่างไรกับกระบวนการลูกของ STDOUT และ STDERR เพราะหากพวกเขาถูกเพิกเฉยภายใต้เงื่อนไขบางอย่าง (ค่อนข้างบ่อย) ในที่สุดกระบวนการลูกก็จะเรียกใช้ระบบเพื่อเขียนไปยัง STDOUT (STDERR ด้วย) ที่เกินบัฟเฟอร์เอาต์พุตที่จัดให้สำหรับกระบวนการโดยระบบปฏิบัติการและระบบปฏิบัติการจะทำให้บล็อกจนกว่ากระบวนการบางอย่างจะอ่านจากบัฟเฟอร์นั้น ดังนั้นด้วยวิธีที่แนะนำในปัจจุบันsubprocess.run(..)สิ่งที่ทำ"สิ่งนี้ไม่ได้จับ stdout หรือ stderr โดยค่าเริ่มต้น" บ่งบอก? แล้วเรื่องsubprocess.check_output(..)STDERR ล่ะ?
Evgeni Sergeev

2
@ พิตต์ใช่ แต่นั่นไม่ใช่สิ่งที่จะถูกดำเนินการโดยตัวอย่าง สังเกตุechoด้านหน้าของสตริงที่ส่งผ่านไปยังPopen? echo my mama didnt love me && rm -rf /ดังนั้นคำสั่งเต็มรูปแบบจะจะ
Chris Arndt

6
นี่เป็นวิธีที่ผิด ๆ คนส่วนใหญ่ต้องการเพียงอย่างเดียวsubprocess.run()หรือพี่น้องรุ่นเก่าsubprocess.check_call()และคณะ subprocess.Popen()สำหรับกรณีที่เหล่านี้ไม่พอเพียงให้ดู os.popen()ไม่ควรพูดถึงเลยหรือมาหลังจาก "แฮกรหัส fork / exec / spawn ของคุณเอง"
tripleee

357

การใช้งานทั่วไป:

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()และมันจะทำตัวเหมือน


44
.readlines()อ่านทุกบรรทัดพร้อมกันนั่นคือมันจะบล็อกจนกว่าจะออกจากกระบวนการย่อย (ปิดท้ายของไปป์) หากต้องการอ่านแบบเรียลไทม์ (หากไม่มีปัญหาการบัฟเฟอร์) คุณสามารถ:for line in iter(p.stdout.readline, ''): print line,
jfs

1
คุณช่วยอธิบายเกี่ยวกับสิ่งที่คุณหมายถึงโดย "ถ้าไม่มีปัญหาการบัฟเฟอร์"? หากกระบวนการบล็อกแน่นอนการเรียกใช้กระบวนการย่อยก็จะบล็อกเช่นกัน สิ่งเดียวกันอาจเกิดขึ้นกับตัวอย่างดั้งเดิมของฉันได้เช่นกัน มีอะไรอีกที่จะเกิดขึ้นได้จากการบัฟเฟอร์
EmmEff

15
กระบวนการลูกอาจใช้การบล็อกบัฟเฟอร์ในโหมดที่ไม่โต้ตอบแทนการบัฟเฟอร์บรรทัดดังนั้นp.stdout.readline()(หมายเหตุ: ไม่มีsที่ท้าย) จะไม่เห็นข้อมูลใด ๆ จนกว่าเด็กจะเติมบัฟเฟอร์ หากเด็กไม่ได้สร้างข้อมูลจำนวนมากผลลัพธ์จะไม่เป็นแบบเรียลไทม์ ดูเหตุผลที่สองในQ: ทำไมไม่ใช้เพียงไพพ์ (popen ())? . การแก้ปัญหาบางอย่างมีให้ในคำตอบนี้ (pexpect, pty, stdbuf)
jfs

4
ปัญหาบัฟเฟอร์จะมีผลเฉพาะเมื่อคุณต้องการเอาต์พุตแบบเรียลไทม์และไม่สามารถใช้กับโค้ดของคุณที่ไม่พิมพ์อะไรจนกว่าจะได้รับข้อมูลทั้งหมด
jfs

3
คำตอบนี้ใช้ได้ในขณะนี้ แต่เราไม่ควรแนะนำPopenงานง่าย ๆอีกต่อไป shell=Trueนอกจากนี้ยังไม่จำเป็นต้องระบุ ลองsubprocess.run()คำตอบหนึ่งข้อ
tripleee

230

คำแนะนำบางอย่างเกี่ยวกับการแยกกระบวนการลูกออกจากกระบวนการเรียก (เริ่มกระบวนการเด็กเป็นพื้นหลัง)

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

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

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 (Windows XP) กระบวนการหลักจะไม่เสร็จสิ้นจนกว่า longtask.py จะทำงานเสร็จ ไม่ใช่สิ่งที่คุณต้องการในสคริปต์ CGI ปัญหาไม่ได้ระบุเฉพาะกับ Python ในชุมชน PHP ปัญหานั้นเหมือนกัน

การแก้ปัญหาคือการส่ง DETACHED_PROCESS กระบวนการสร้างค่าสถานะไปยังฟังก์ชัน CreateProcess พื้นฐานใน Windows API หากคุณติดตั้ง pywin32 คุณสามารถนำเข้าการตั้งค่าสถานะจากโมดูล 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 เช่นกัน การทดลองบางอย่างแสดงให้เห็นว่าปัญหาดูเหมือนจะแบ่งปัน sys.stdout และวิธีแก้ปัญหาการทำงานมีดังต่อไปนี้:

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

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


ฉันสังเกตว่า "การเล่นโวหาร" ที่เป็นไปได้ด้วยการพัฒนาแอพ py2exe ใน pydev + eclipse ฉันสามารถบอกได้ว่าสคริปต์หลักไม่ได้ถูกแยกออกเนื่องจากหน้าต่างเอาต์พุตของ eclipse ไม่ได้ถูกยกเลิก แม้ว่าสคริปต์จะดำเนินการจนแล้วเสร็จก็ยังคงรอการส่งคืน แต่เมื่อฉันพยายามรวบรวมเพื่อปฏิบัติการ py2exe พฤติกรรมที่คาดหวังเกิดขึ้น (เรียกใช้กระบวนการเป็นแฝดแล้วออกจาก) ฉันไม่แน่ใจ แต่ชื่อปฏิบัติการไม่ได้อยู่ในรายการกระบวนการอีกต่อไป ใช้ได้กับทุกวิธีการ (os.system ("start *"), os.spawnl กับ os.P_DETACH, โปรแกรมย่อย ฯลฯ )
maranas


5
ต่อไปนี้ไม่ถูกต้อง: "[o] n windows (win xp) กระบวนการหลักจะไม่เสร็จสิ้นจนกว่า longtask.py จะทำงานเสร็จ" พาเรนต์จะออกตามปกติ แต่หน้าต่างคอนโซล (อินสแตนซ์ conhost.exe) จะปิดก็ต่อเมื่อกระบวนการที่แนบมาครั้งสุดท้ายจบการทำงานและลูกอาจสืบทอดคอนโซลของพาเรนต์ การตั้งค่าDETACHED_PROCESSในการcreationflagsหลีกเลี่ยงการนี้โดยการป้องกันเด็กจากการสืบทอดหรือการสร้างคอนโซล หากคุณต้องการคอนโซลใหม่ให้ใช้CREATE_NEW_CONSOLE(0x00000010)
Eryk Sun

1
ฉันไม่ได้หมายความว่าการดำเนินการตามกระบวนการเดี่ยวไม่ถูกต้อง ที่กล่าวว่าคุณอาจต้องตั้งค่าการจัดการมาตรฐานให้กับไฟล์ไพพ์หรือos.devnullเพราะโปรแกรมคอนโซลบางตัวจบการทำงานโดยมีข้อผิดพลาดเป็นอย่างอื่น สร้างคอนโซลใหม่เมื่อคุณต้องการให้กระบวนการลูกโต้ตอบกับผู้ใช้พร้อมกับกระบวนการหลัก มันจะทำให้สับสนในการพยายามทำทั้งสองอย่างในหน้าต่างเดียว
Eryk Sun

1
ไม่มีวิธีที่ผู้ไม่เชื่อเรื่องพระเจ้าที่มีกระบวนการทำงานในพื้นหลัง?
Charlie Parker

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

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


6
ไม่รู้เลยว่าฉันหมายถึงอะไรเมื่อเกือบสิบปีที่แล้ว (ตรวจสอบวันที่!) แต่ถ้าฉันต้องเดาก็คงเป็นเพราะไม่มีการตรวจสอบความถูกต้อง
nimish

1
ตอนนี้ควรชี้ไปsubprocessที่โซลูชันอเนกประสงค์และพกพาเล็กน้อย แน่นอนว่าการรันคำสั่งภายนอกนั้นเป็นสิ่งที่ไม่สามารถทำได้อย่างแน่นอน (คุณต้องแน่ใจว่าคำสั่งนั้นมีอยู่ในทุกสถาปัตยกรรมที่คุณต้องการสนับสนุน) และส่งผ่านอินพุตของผู้ใช้เนื่องจากคำสั่งภายนอกนั้นไม่ปลอดภัย
tripleee

1
สังเกตการประทับเวลาของผู้ชายคนนี้: คำตอบ "ถูกต้อง" มีคะแนนโหวต 40x และเป็นคำตอบ # 1
nimish

วิธีการแก้ปัญหาหนึ่งที่ทำงานให้ฉันสำหรับการทำงานสิ่ง NodeJS
Nikolay Shindarov

147

ฉันขอแนะนำให้ใช้โมดูลsubprocessแทนที่จะเป็น os.system เพราะมันช่วยให้คุณรอดพ้นจากเชลล์และปลอดภัยกว่ามาก

subprocess.call(['ping', 'localhost'])

หากคุณต้องการสร้างรายการจากคำสั่งพร้อมพารามิเตอร์รายการที่สามารถใช้กับsubprocessเวลาshell=Falseได้จากนั้นใช้shlex.splitวิธีง่าย ๆ ในการทำเอกสารนี้docs.python.org/2/library/shlex.html#shlex.split ( เป็นวิธีที่แนะนำตาม docs docs.python.org/2/library/subprocess.html#popen-constructor ) ซึ่งเป็นวิธีที่แนะนำ)
Daniel F

6
สิ่งนี้ไม่ถูกต้อง: " มันช่วยให้คุณปลอดภัยและปลอดภัยกว่า " กระบวนการย่อยไม่ได้หลบหนีเชลล์กระบวนการย่อยไม่ผ่านคำสั่งของคุณผ่านเชลล์ดังนั้นจึงไม่จำเป็นต้องใช้เชลล์ยกเว้น
Lie Ryan

143
import os
cmd = 'ls -al'
os.system(cmd)

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


10
popen จะเลิกในความโปรดปรานของกระบวนการย่อย
ฟ็อกซ์วิลสัน

คุณสามารถบันทึกผลลัพธ์ของคุณด้วยการเรียกใช้ os.system เนื่องจากทำงานเหมือนเชลล์ UNIX เองเช่นเช่น os.system ('ls -l> test2.txt')
Stefan Gruenwald

97

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

แหล่งที่มา:

นี่คือห้องสมุดทั้งหมด:

หวังว่านี่จะช่วยคุณในการตัดสินใจว่าจะใช้ไลบรารีใด :)

กระบวนการย่อย

กระบวนการย่อยช่วยให้คุณสามารถเรียกใช้คำสั่งภายนอกและเชื่อมต่อกับอินพุต / เอาต์พุต / ข้อผิดพลาดของไปป์ (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.systemและos.popen(หมายเหตุ: นอกจากนี้ยังมี subprocess.popen) subprocess.runระบบปฏิบัติการจะใช้เปลือกและเป็นทางเลือกที่ง่ายสำหรับคนที่ไม่จำเป็นต้องหรือไม่ทราบวิธีการใช้งาน

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

ดวลจุดโทษ

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 เป็นห้องสมุดสำหรับโปรแกรม Python แบบสคริปต์ คุณสามารถเรียกโปรแกรมเช่นฟังก์ชั่นshได้ Plumbum มีประโยชน์ถ้าคุณต้องการเรียกใช้ไพพ์ไลน์โดยไม่มีเชลล์

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

pexpect

pexpect ช่วยให้คุณวางไข่แอปพลิเคชันสำหรับเด็กควบคุมและค้นหารูปแบบในผลลัพธ์ได้ นี่เป็นทางเลือกที่ดีกว่าสำหรับกระบวนการย่อยสำหรับคำสั่งที่คาดว่าจะมี 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 เป็นไลบรารี Python 2.5 และ 2.7 มันช่วยให้คุณสามารถรันคำสั่งโลคัลและรีโมตเชลล์ Fabric เป็นทางเลือกง่าย ๆ สำหรับการรันคำสั่งใน secure shell (SSH)

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

ราชทูต

นักการทูตเรียกว่า "subprocess for human" มันถูกใช้เป็นเครื่องห่อหุ้มสิ่งอำนวยความสะดวกรอบ ๆsubprocessโมดูล

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

คำสั่ง

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

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


74

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

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

แต่ตอนนี้ดูเหมือนจะเป็นเครื่องมือที่ดี: (อินเตอร์เฟซหลามกระบวนการย่อย)sh

ดูตัวอย่าง:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)

73

ตรวจสอบคลัง Python "pexpect" ด้วย

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

child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

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

70

ด้วยห้องสมุดมาตรฐาน

ใช้โมดูลย่อย (Python 3):

import subprocess
subprocess.run(['ls', '-l'])

เป็นวิธีมาตรฐานที่แนะนำ อย่างไรก็ตามงานที่ซับซ้อนมากขึ้น (ไปป์, เอาท์พุต, อินพุทและอื่น ๆ ) นั้นน่าเบื่อในการสร้างและเขียน

หมายเหตุเกี่ยวกับเวอร์ชั่น Python: หากคุณยังใช้ Python 2 อยู่subprocess.call ก็จะทำงานในลักษณะเดียวกัน

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

import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

ด้วยการพึ่งพาจากภายนอก

หากคุณไม่สนใจการพึ่งพาจากภายนอกให้ใช้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ติดตั้งโดย


69

หากคุณต้องการเอาต์พุตจากคำสั่งที่คุณเรียกใช้คุณสามารถใช้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'

ให้สังเกตพารามิเตอร์ของเชลล์ด้วย

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


1
โปรดทราบว่าcheck_outputต้องมีรายการมากกว่าสตริง subprocess.check_output("ls -l /dev/null".split())หากคุณไม่ได้ขึ้นอยู่กับพื้นที่ที่ยกมาเพื่อให้การโทรของคุณถูกต้องที่ง่ายวิธีที่สามารถอ่านได้มากที่สุดที่จะทำคือ
Bruno Bronosky

56

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

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
ฉันคิดว่ามันเป็นที่ยอมรับได้สำหรับคำสั่งฮาร์ดโค้ดหากมันเพิ่มความสามารถในการอ่าน
Adam Matan

54

ปรับปรุง:

subprocess.runเป็นวิธีที่แนะนำใน Python 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')

คำตอบเดิม:

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

ตัวอย่างการใช้งานจาก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
[<Response 'uptime'>]


36

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

ใช้ง่ายsubprocess.runซึ่งส่งคืนCompletedProcessวัตถุ:

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

ทำไม?

ตั้งแต่ Python 3.5 เอกสารแนะนำsubprocess.run :

วิธีที่แนะนำในการเรียกใช้กระบวนการย่อยคือการใช้ฟังก์ชั่น run () สำหรับทุกกรณีการใช้งานที่สามารถจัดการได้ สำหรับกรณีการใช้งานขั้นสูงเพิ่มเติมสามารถใช้อินเตอร์เฟส Popen พื้นฐานได้โดยตรง

นี่คือตัวอย่างของการใช้งานที่ง่ายที่สุดเท่าที่จะเป็นไปได้

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

runรอให้คำสั่งเสร็จสิ้นเป็นผลสำเร็จจากนั้นส่งคืนCompletedProcessวัตถุ มันอาจเพิ่มTimeoutExpired(ถ้าคุณให้มันtimeout=โต้เถียง) หรือCalledProcessError(ถ้ามันล้มเหลวและคุณผ่านcheck=True)

ในขณะที่คุณอาจอนุมานจากตัวอย่างข้างต้น stdout และ stderr ทั้งสองได้รับการไพพ์ไปยัง stdout ของคุณเองและ stderr โดยค่าเริ่มต้น

เราสามารถตรวจสอบวัตถุที่ส่งคืนและดูคำสั่งที่ได้รับและ returncode:

>>> completed_process.args
'python --version'
>>> completed_process.returncode
0

การจับเอาท์พุท

หากคุณต้องการจับเอาท์พุทคุณสามารถส่งผ่านsubprocess.PIPEไปยังที่เหมาะสมstderrหรือstdout:

>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(ฉันคิดว่ามันน่าสนใจและขัดข้องเล็กน้อยที่ข้อมูลรุ่นถูกนำไปใช้กับ stderr แทนที่จะเป็น stdout)

ส่งรายการคำสั่ง

หนึ่งอาจย้ายจากการให้สตริงคำสั่งด้วยตนเอง (เช่นคำถามแนะนำ) เพื่อจัดทำสตริงที่สร้างโดยทางโปรแกรม อย่าสร้างสตริงโดยทางโปรแกรม นี่เป็นปัญหาด้านความปลอดภัยที่อาจเกิดขึ้น มันจะดีกว่าถ้าคุณไม่เชื่อถืออินพุต

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\n'

หมายเหตุเท่านั้น argsควรส่งผ่านตำแหน่งเท่านั้น

ลายเซ็นเต็ม

นี่คือลายเซ็นจริงในแหล่งที่มาและแสดงโดยhelp(run):

def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

popenargsและkwargsจะได้รับกับPopenคอนสตรัค inputสามารถเป็นสตริงไบต์ (หรือ unicode หากระบุการเข้ารหัสหรือuniversal_newlines=True ) ที่จะถูกไพพ์ไปยัง stdin ของกระบวนการย่อย

เอกสารอธิบายtimeout=และcheck=Trueดีกว่าที่ฉันสามารถ:

อาร์กิวเมนต์การหมดเวลาถูกส่งผ่านไปยัง Popen.communicate () หากการหมดเวลาหมดอายุกระบวนการลูกจะถูกฆ่าและรอ ข้อยกเว้น TimeoutExpired จะถูกยกขึ้นอีกครั้งหลังจากกระบวนการลูกสิ้นสุดลง

หากการตรวจสอบเป็นจริงและกระบวนการออกจากด้วยรหัสทางออกที่ไม่ใช่ศูนย์จะมีการยกข้อยกเว้น CalledProcessError คุณลักษณะของข้อยกเว้นนั้นจะเก็บอาร์กิวเมนต์รหัสการออกและ stdout และ stderr หากถูกจับ

และตัวอย่างcheck=Trueนี้ดีกว่าอย่างใดอย่างหนึ่งที่ฉันสามารถหา:

>>> 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(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

โปรดทราบว่าสิ่งนี้บ่งชี้ว่ารายการ args เท่านั้นที่ควรส่งผ่านตำแหน่ง ดังนั้นให้ส่งอาร์กิวเมนต์ที่เหลือเป็นอาร์กิวเมนต์ของคำหลัก

popen

เมื่อใช้Popenแทน ฉันจะต่อสู้เพื่อหากรณีการใช้งานตามข้อโต้แย้งเพียงอย่างเดียว อย่างไรก็ตามการใช้งานโดยตรงPopenจะช่วยให้คุณสามารถเข้าถึงวิธีการรวมถึงpoll 'send_signal', 'ยุติ' และ 'รอ'

นี่คือPopenลายเซ็นตามที่กำหนดในแหล่งที่มา ฉันคิดว่านี่คือการห่อหุ้มข้อมูลที่แม่นยำที่สุด (ตรงข้ามกับhelp(Popen)):

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

แต่ได้ข้อมูลมากขึ้นคือเอกสาร :Popen

subprocess.Popen(args, bufsize=-1, executable=None, stdin=None,
                 stdout=None, stderr=None, preexec_fn=None, close_fds=True,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

ดำเนินการโปรแกรมย่อยในกระบวนการใหม่ บน POSIX คลาสใช้พฤติกรรม os.execvp () - like เพื่อเรียกใช้งานโปรแกรมลูก บน Windows คลาสใช้ฟังก์ชัน Windows CreateProcess () อาร์กิวเมนต์ของ Popen มีดังนี้

การทำความเข้าใจกับเอกสารที่เหลืออยู่Popenจะเป็นแบบฝึกหัดสำหรับผู้อ่าน


ตัวอย่างง่ายๆของการสื่อสารสองทางระหว่างกระบวนการหลักและกระบวนการย่อยสามารถดูได้ที่นี่: stackoverflow.com/a/52841475/1349673
James Hirschorn

ตัวอย่างแรกอาจจะมีshell=Trueหรือ (ดีกว่า) ส่งคำสั่งเป็นรายการ
tripleee

35

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

รับข้อมูลเพิ่มเติมได้ที่นี่


2
ในขณะที่ฉันเห็นด้วยกับคำแนะนำโดยรวมsubprocessไม่ได้ลบปัญหาด้านความปลอดภัยทั้งหมดและมีปัญหาที่น่ารำคาญของตัวเอง
tripleee

33

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

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> 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

28

ใช้:

import os

cmd = 'ls -al'

os.system(cmd)

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

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


2
มันเลิกใช้แล้ว ใช้กระบวนการย่อย
Corey Goldberg

28

มันอาจเป็นเรื่องง่าย:

import os
cmd = "your command"
os.system(cmd)

1
นี้ล้มเหลวที่จะชี้ให้เห็นข้อบกพร่องซึ่งจะอธิบายในรายละเอียดมากขึ้นในPEP-324 เอกสารประกอบสำหรับชัดเจนแนะนำให้หลีกเลี่ยงมันในความโปรดปรานของos.system subprocess
tripleee

25

ฉันค่อนข้างชอบshell_commandสำหรับความเรียบง่าย มันสร้างขึ้นที่ด้านบนของโมดูลย่อย

นี่คือตัวอย่างจากเอกสาร:

>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py  shell_command.py  test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0

24

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

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

ฉันลองกระบวนการย่อยและการดำเนินการเสร็จสมบูรณ์ อย่างไรก็ตาม <b> ไม่สามารถสื่อสารกับ <a> ทุกอย่างเป็นปกติเมื่อฉันเรียกใช้ทั้งจากสถานี

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

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

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


1
คุณหมายถึงอะไรโดย"ใครก็ตามที่เรียกใช้ kwrite ไม่ได้เป็น subprocess" ?
Peter Mortensen

23

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


22

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


22

ฉันมักจะใช้subprocesssร่วมกับ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)

17

ปลั๊กไร้ยางอายฉันเขียนห้องสมุดสำหรับสิ่งนี้: P https://github.com/houqp/shell.py

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

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

16

ใน 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

15

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

ตัวอย่างที่มีตัวจัดคิวงาน:

import os
os.system('ts <your-command>')

หมายเหตุเกี่ยวกับตัวจัดคิวงาน ( ts):

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

    ts -S <number-of-slots>

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


1
tsไม่ได้เป็นมาตรฐานสำหรับ distro ใด ๆ ที่ฉันรู้ถึงแม้ว่าตัวชี้ไปยังatมีประโยชน์เล็กน้อย คุณควรพูดถึงbatchเช่นกัน อย่างอื่นos.system()ควรแนะนำอย่างน้อยพูดถึงนั่นsubprocessคือการแนะนำแทน
tripleee


15

ในการดึงรหัสเครือข่ายจากOpenStack Neutron :

#!/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 |
+--------------------------------------+------------+------+

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

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

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