目次
1. โมดูล subprocess ของ Python คืออะไร
ภาพรวม
โมดูลsubprocess ของ Python เป็นเครื่องมืออันทรงพลังสำหรับเรียกใช้คำสั่งระบบหรือโปรแกรมภายนอกจาก Python โดยตรง การใช้โมดูลนี้ทำให้สามารถจัดการ input/output มาตรฐานและจัดการโพรเซสได้ง่าย ช่วยให้โปรแกรม Python เชื่อมต่อกับโปรแกรมอื่นๆ ได้สะดวกขึ้น โดยเป็นวิธีที่ปลอดภัยและยืดหยุ่นกว่า os.system() หรือ commands ที่เคยใช้มาก่อนการใช้งานหลัก
- รันคำสั่ง Shell: เรียกใช้คำสั่งระบบอย่างง่าย
- จัดการโพรเซส: รันโปรแกรมภายนอกและ redirect input/output
- ประมวลผลแบบ asynchronous: จัดการงานที่ใช้เวลานานหรือรันหลายงานพร้อมกัน
Ad
2. วิธีใช้พื้นฐาน: subprocess.run()
ตัวอย่างการใช้งานพื้นฐาน
subprocess.run() คือฟังก์ชันที่ใช้สำหรับรันคำสั่งระบบอย่างง่ายจาก Python ตัวอย่างเช่น การแสดงรายการไฟล์ในไดเรกทอรี สามารถใช้โค้ดดังนี้import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)โค้ดนี้จะรันคำสั่ง ls -l แล้วบันทึกผลลัพธ์ไว้ใน stdout เพื่อใช้งานใน Python โดย capture_output=True จะจับผลลัพธ์ออกมา และ text=True จะให้ผลลัพธ์เป็นข้อความการจัดการข้อผิดพลาด
เมื่อใช้subprocess.run() หากคำสั่งล้มเหลว สามารถใช้ stderr เพื่อดึงข้อความ error ได้ และตรวจสอบผลการทำงานด้วย returncoderesult = subprocess.run(['ls', 'nonexistentfile'], capture_output=True, text=True)
if result.returncode != 0:
print(f"เกิดข้อผิดพลาด: {result.stderr}")ในตัวอย่างนี้ ถ้าระบุไฟล์ที่ไม่มีอยู่ จะเห็นข้อความ error ผ่าน standard error
3. การประมวลผลแบบ asynchronous: subprocess.Popen()
การประมวลผลแบบ asynchronous ด้วย Popen
subprocess.run() จะรันแบบ synchronous (ต้องรอคำสั่งจบก่อนถึงไปต่อ) แต่ถ้าใช้ subprocess.Popen() จะสามารถรันโพรเซสแบบ asynchronous คือ ทำงานอย่างอื่นไปพร้อมกันได้import subprocess
proc = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE)
print("เริ่มโปรเซสแล้ว")
proc.wait()
print("โปรเซสเสร็จสิ้นแล้ว")ในโค้ดนี้ sleep 5 จะรันแบบ background และสามารถทำงานอย่างอื่นในขณะรอได้การควบคุม input/output มาตรฐาน
Popen สามารถควบคุม redirect input/output ได้ละเอียด เช่น โค้ดต่อไปนี้จะอ่านไฟล์ ส่งผ่าน cat และเขียนผลลัพธ์ไปไฟล์ใหม่with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
proc = subprocess.Popen(['cat'], stdin=infile, stdout=outfile)
proc.wait()ทำให้สามารถ redirect input/output ระหว่างโปรแกรมกับไฟล์ได้อย่างยืดหยุ่นAd
4. ตัวอย่างการใช้งาน: สคริปต์อัตโนมัติ
การสำรองไฟล์ (Backup)
subprocess เหมาะกับการจัดการงานระบบหรือ automate task เช่น โค้ดต่อไปนี้จะสำรองไฟล์ไปยังโฟลเดอร์ backup อัตโนมัติimport subprocess
files_to_backup = ['file1.txt', 'file2.txt', 'file3.txt']
backup_dir = '/backup/directory/'
for file in files_to_backup:
subprocess.run(['cp', file, backup_dir])โค้ดนี้จะคัดลอกไฟล์ที่กำหนดไปยังโฟลเดอร์ backup ช่วยให้ตั้งเวลา backup ได้โดยง่ายใช้งานกับ CI/CD Pipeline
subprocess ใช้งานได้กับระบบ CI/CD เช่น รันสคริปต์ทดสอบ หรือ deploy อัตโนมัติ เช่น หลังทดสอบผ่านจึง deploy ต่อได้
5. ความปลอดภัยและแนวทางที่ควรใช้
ความเสี่ยงของ shell=True
shell=True ใช้เมื่อรันคำสั่งผ่าน shell ซึ่งมีความเสี่ยงด้านความปลอดภัยโดยเฉพาะถ้ารับ input จากผู้ใช้โดยตรง อาจเกิด shell injection ได้ ควรใช้ shell=False เป็นหลักimport subprocess
# วิธีที่แนะนำ (ปลอดภัย)
subprocess.run(['ls', '-l'])
# shell=True (ต้องระวัง)
subprocess.run('ls -l', shell=True)รองรับหลายระบบปฏิบัติการ
คำสั่งระบบจะแตกต่างกันในแต่ละ OS สามารถใช้platform เพื่อตรวจสอบ OS และรันคำสั่งที่เหมาะสมimport platform
import subprocess
if platform.system() == "Windows":
subprocess.run(['dir'], shell=True)
else:
subprocess.run(['ls', '-l'])Ad
6. แก้ไขปัญหาและ debug
ข้อผิดพลาดที่พบบ่อยและแนวทางแก้
เมื่อใช้subprocess อาจเจอ error เช่น ไม่พบไฟล์หรือสิทธิ์ไม่พอ สามารถตรวจสอบ stderr และ returncode เพื่อดูรายละเอียดข้อผิดพลาดเคล็ดลับสำหรับ debug
ถ้าใส่check=True จะให้ raise exception เมื่อคำสั่งล้มเหลว สามารถจับ exception และเก็บ log ได้ง่ายขึ้นimport subprocess
try:
result = subprocess.run(['ls', '-l'], check=True, capture_output=True, text=True)
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"เกิดข้อผิดพลาด: {e}")Ad
7. ประมวลผลแบบ asynchronous กับ asyncio
การประมวลผลแบบ asynchronous ด้วย asyncio
เมื่อใช้asyncio ร่วมกับ subprocess จะสามารถจัดการงานหลายอย่างพร้อมกันแบบ async ได้ ตัวอย่างต่อไปนี้ใช้ asyncio รัน ls แบบ async และรับค่าผลลัพธ์import asyncio
import subprocess
async def run_command():
proc = await asyncio.create_subprocess_exec('ls', '-l',
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
if stdout:
print(f'[stdout]n{stdout.decode()}')
if stderr:
print(f'[stderr]n{stderr.decode()}')
asyncio.run(run_command())โค้ดนี้จะรันคำสั่งแบบ async และดึงผลลัพธ์มาตรวจสอบได้ ช่วยให้บริหารงาน async ได้มีประสิทธิภาพยิ่งขึ้น



