จะเรียกเชลล์สคริปต์จากโค้ดไพ ธ อนได้อย่างไร?


คำตอบ:


252

subprocessโมดูลจะช่วยให้คุณออก

ตัวอย่างเล็ก ๆ น้อย ๆ โจ๋งครึ่ม:

>>> import subprocess
>>> subprocess.call(['./test.sh']) # Thanks @Jim Dennis for suggesting the []
0 
>>> 

test.shเชลล์สคริปต์ธรรมดาอยู่ที่ไหนและ0เป็นค่าส่งคืนสำหรับการรันนี้


11
หมายเหตุ: มันจะดีกว่าที่จะผ่าน subprocess.call () รายการมากกว่าสตริง (ดูคำสั่งเพื่อ Hugo24 ด้านล่างสำหรับตัวอย่างและเหตุผล)
Jim Dennis

1
ลิงก์ไปยังบทช่วยสอนใช้งานไม่ได้
Kshitij Saraogi

6
สิ่งนี้ให้: OSError: [Errno 13] การอนุญาตถูกปฏิเสธ สคริปต์ของฉันไม่จำเป็นต้องใช้กับ sudo @Manoj Govindan
alper

6
ด้วยอาร์กิวเมนต์: subprocess.call (['./ test.sh', 'param1', 'param2'])
Henry

2
@alper chmod +x script.shไปโฟลเดอร์ที่คุณได้วางสคริปต์และเรียกใช้คำสั่ง หมายเหตุ: script.sh เป็นตัวยึดสำหรับสคริปต์ของคุณแทนที่มันตามนั้น
Tom J Muthirenthi

105

มีบางวิธีที่ใช้os.popen()(คัดค้าน) หรือsubprocessโมดูลทั้งหมดแต่วิธีนี้

import os
os.system(command)

เป็นหนึ่งในวิธีที่ง่ายที่สุด


1
ทำไมนี่ไม่ใช่คำตอบที่ได้รับการโหวตมากที่สุด? ไม่ต้องนำเข้าโมดูลโซลูชั่นที่ดีกว่า? ต้องเป็นข้อเสียเปรียบที่นี่?
boulder_ruby

6
ด้วยsubprocessคุณสามารถจัดการท่ออินพุต / เอาต์พุต / ข้อผิดพลาด นอกจากนี้ยังเป็นการดีกว่าเมื่อคุณมีอาร์กิวเมนต์มากมาย - ด้วยos.command()คุณจะต้องสร้างบรรทัดคำสั่งทั้งหมดด้วยการยกเว้นอักขระพิเศษโดยsubprocessมีรายการอาร์กิวเมนต์ที่ง่าย แต่สำหรับงานง่ายๆos.command() อาจเพียงพอ
Michał Niklas

1
หากต้องการอ้างอิงจากลิงก์ดังกล่าว:The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; *using that module is preferable to using this function.*
Maximilian

42

ในกรณีที่คุณต้องการส่งพารามิเตอร์บางตัวไปยังเชลล์สคริปต์ของคุณคุณสามารถใช้เมธอดshlex.split () :

import subprocess
import shlex
subprocess.call(shlex.split('./test.sh param1 param2'))

ด้วยtest.shในโฟลเดอร์เดียวกัน:

#!/bin/sh
echo $1
echo $2
exit 0

ขาออก:

$ python test.py 
param1
param2

นี่คือสง่างาม
คาเลบ


15

ใช้โมดูลย่อยตามที่กล่าวไว้ข้างต้น

ฉันใช้มันแบบนี้:

subprocess.call(["notepad"])

13
หมายเหตุ: การเรียก subprocess พร้อมรายการนั้นปลอดภัยกว่าเพราะไม่จำเป็นต้องผ่านสตริง (อาจไม่ถูกแก้ไข) ผ่านเชลล์สำหรับการวิเคราะห์ / ตีความ รายการแรกในรายการจะเป็นไฟล์เรียกทำงานและรายการอื่น ๆ ทั้งหมดจะถูกส่งเป็นอาร์กิวเมนต์
Jim Dennis

13

ฉันใช้ python 3.5 และ subprocess.call (['./ test.sh']) ไม่ทำงานสำหรับฉัน

ฉันให้คำตอบสามข้อกับสิ่งที่คุณต้องการทำกับผลลัพธ์

1 - สคริปต์การโทร คุณจะเห็นผลลัพธ์ในเทอร์มินัลของคุณ ผลลัพธ์คือตัวเลข

import subprocess 
output = subprocess.call(['test.sh'])

2 - การเรียกใช้และการดัมพ์และข้อผิดพลาดในสตริง คุณไม่เห็นการดำเนินการในเทอร์มินัลเว้นแต่คุณจะพิมพ์ (stdout) Shell = True เนื่องจากข้อโต้แย้งใน Popen ใช้ไม่ได้สำหรับฉัน

import subprocess
from subprocess import Popen, PIPE

session = subprocess.Popen(['test.sh'], stdout=PIPE, stderr=PIPE)
stdout, stderr = session.communicate()

if stderr:
    raise Exception("Error "+str(stderr))

3 - เรียกสคริปต์และดัมพ์คำสั่ง echo ของ temp.txt ใน temp_file

import subprocess
temp_file = open("temp.txt",'w')
subprocess.call([executable], stdout=temp_file)
with open("temp.txt",'r') as file:
    output = file.read()
print(output)

อย่าลืมดูกระบวนการย่อยของ doc


1
หมายเหตุ อย่าใช้ stdout = ท่อหรือ stderr = subprocess.callท่อด้วย กระบวนการลูกจะบล็อกถ้ามันสร้างผลผลิตเพียงพอที่จะไปป์เพื่อเติมบัฟเฟอร์ท่อของระบบปฏิบัติการในขณะที่ไม่ได้อ่านไปป์

4

โมดูลย่อยเป็นโมดูลที่ดีในการเปิดใช้งานกระบวนการย่อย คุณสามารถใช้มันเพื่อเรียกคำสั่งเชลล์ดังนี้:

subprocess.call(["ls","-l"]);
#basic syntax
#subprocess.call(args, *)

คุณสามารถดูเอกสารประกอบได้ที่นี่

หากคุณมีสคริปต์ของคุณเขียนในไฟล์. sh หรือสตริงที่ยาวคุณสามารถใช้โมดูล os.system ได้ มันค่อนข้างง่ายและง่ายต่อการโทร:

import os
os.system("your command here")
# or
os.system('sh file.sh')

คำสั่งนี้จะเรียกใช้สคริปต์หนึ่งครั้งเพื่อเสร็จสิ้นและบล็อกจนกว่าจะออก


คุณไม่ต้องนำเข้าระบบด้วยหรือไม่
ScottyBlades

ไม่คุณทำไม่ได้; ลองเปิดเปลือก Python และเรียกใช้ตัวอย่างนี้
Descartes

4

ในกรณีที่สคริปต์มีข้อโต้แย้งหลายประการ

#!/usr/bin/python

import subprocess
output = subprocess.call(["./test.sh","xyz","1234"])
print output

ผลลัพธ์จะให้รหัสสถานะ หากสคริปต์ทำงานได้สำเร็จจะให้ค่า 0 เป็นจำนวนเต็มไม่ใช่ศูนย์

podname=xyz  serial=1234
0

ด้านล่างเป็นสคริปต์เชลล์ test.sh

#!/bin/bash

podname=$1
serial=$2
echo "podname=$podname  serial=$serial"

2

กระบวนการย่อยดี แต่บางคนอาจชอบscriptineดีกว่า Scriptine มีชุดระดับสูงมากขึ้นของวิธีการเช่นshell.call (args) , path.rename (new_name)และpath.move (src, DST) Scriptine ขึ้นอยู่กับกระบวนการย่อยและอื่น ๆ

ข้อเสียสองประการของ scriptine:

  • ระดับเอกสารปัจจุบันจะครอบคลุมมากขึ้นแม้ว่าจะเพียงพอแล้ว
  • ซึ่งแตกต่างจากกระบวนการย่อยแพ็คเกจสคริปต์ไม่ได้ติดตั้งตามค่าเริ่มต้น

2

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันสะดุดเมื่อเร็ว ๆ นี้และท้ายที่สุดฉันก็เข้าใจผิดตั้งแต่Subprocess API ที่เปลี่ยนไปตั้งแต่ python 3.5

วิธีใหม่ในการเรียกใช้งานสคริปต์ภายนอกคือการใช้runฟังก์ชันซึ่งเรียกใช้คำสั่งที่อธิบายโดย args รอให้คำสั่งเสร็จสมบูรณ์จากนั้นส่งคืนอินสแตนซ์ CompletedProcess

import subprocess

subprocess.run(['./test.sh'])

1

หากไฟล์เชลล์สคริปต์ของคุณไม่มีสิทธิ์ดำเนินการให้ทำตามวิธีดังต่อไปนี้

import subprocess
subprocess.run(['/bin/bash', './test.sh'])

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