Một số quy tắc ngón tay cái cho subprocess
.
- Không bao giờ sử dụng
shell=True
. Nó không cần thiết phải gọi một quá trình shell bổ sung để gọi chương trình của bạn.
- Khi gọi các tiến trình, các đối số được chuyển xung quanh dưới dạng danh sách.
sys.argv
trong python là một danh sách, và như vậy là argv
trong C. Vì vậy, bạn vượt qua một danh sách để Popen
gọi trình con, không phải là một chuỗi.
- Đừng chuyển hướng
stderr
đến a PIPE
khi bạn không đọc nó.
- Đừng chuyển hướng
stdin
khi bạn không viết thư cho nó.
Thí dụ:
import subprocess, time, os, sys
cmd = ["rsync.exe", "-vaz", "-P", "source/" ,"dest/"]
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
print(">>> " + line.rstrip())
Điều đó nói rằng, có khả năng rsync đệm đầu ra của nó khi nó phát hiện ra rằng nó được kết nối với một đường ống thay vì một thiết bị đầu cuối. Đây là hành vi mặc định - khi được kết nối với một đường ống, các chương trình phải xóa rõ ràng stdout để có kết quả thời gian thực, nếu không thư viện C tiêu chuẩn sẽ đệm.
Để kiểm tra điều đó, hãy thử chạy điều này thay thế:
cmd = [sys.executable, 'test_out.py']
và tạo một test_out.py
tệp có nội dung:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Việc thực thi quy trình con đó sẽ cung cấp cho bạn "Xin chào" và đợi 10 giây trước khi đưa ra "Thế giới". Nếu điều đó xảy ra với mã python ở trên mà không phải với rsync
, điều đó có nghĩa là rsync
bản thân nó đang lưu đầu ra vào bộ đệm, vì vậy bạn không may mắn.
Một giải pháp sẽ là kết nối trực tiếp với a pty
, sử dụng một cái gì đó như pexpect
.