2012-04-03 27 views
37
import os 

import subprocess 

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

out,err = proc.communicate() 

print out 

Kịch bản này sẽ in tất cả các tệp có hậu tố .bc tuy nhiên nó trả về một danh sách trống. Nếu tôi làm ls * .bc theo cách thủ công trong dòng lệnh, nó hoạt động. Làm ['ls', 'test.bc'] bên trong tập lệnh cũng hoạt động nhưng vì lý do nào đó, biểu tượng ngôi sao không hoạt động .. Bất kỳ ý tưởng nào?Sử dụng thẻ đại diện con của Python subprocess

+0

liên quan: [Wildcard không làm việc trong cuộc gọi subprocess bằng cách sử dụng shlex] (http: // stackoverf low.com/q/7156892/4279) – jfs

Trả lời

41

Bạn cần cung cấp shell=True để thực thi lệnh thông qua trình thông dịch trình bao. Nếu bạn làm điều đó tuy nhiên, bạn không còn có thể cung cấp một danh sách như là đối số đầu tiên, bởi vì các đối số sẽ được trích dẫn sau đó. Thay vào đó, xác định dòng lệnh thô như bạn muốn nó được thông qua vào vỏ:

proc = subprocess.Popen('ls *.bc', shell=True, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE) 
+0

Cảm ơn điều này đã làm việc tốt. Một số ví dụ mà tôi tìm thấy trên internet có danh sách là đối số đầu tiên của họ vì lý do nào đó – Cemre

+9

@Cemre: Điều đó thường được khuyến khích vì bạn * không * muốn trình bao giải thích các đối số. Hãy tưởng tượng bạn chuyển người dùng nhập vào một lệnh như trong ''ls' + user_supplied_path'. Người dùng chỉ có thể nhập đường dẫn '; shutdown -s' và hệ thống sẽ dừng lại! Nếu bạn sử dụng '['ls', user_supplied_path]', bạn ngăn chặn kiểu tiêm này. –

37

Mở rộng * glob là một phần của vỏ, nhưng theo mặc định subprocess không không gửi lệnh của bạn thông qua một vỏ, vì vậy lệnh (đối số đầu tiên, ls) được thực hiện, sau đó một chữ cái * được sử dụng làm đối số.

Đây là một điều tốt, xem the warning block in the "Frequently Used Arguments" section, của tài liệu về quy trình con. Nó chủ yếu thảo luận về các tác động bảo mật, nhưng cũng có thể giúp tránh các lỗi lập trình ngớ ngẩn (vì không có các ký tự shell ma thuật phải lo lắng)

Khiếu nại chính của tôi với shell=True là nó thường có cách tốt hơn để giải quyết vấn đề - với ví dụ của bạn, bạn nên sử dụng the glob module:

import glob 
files = glob.glob("*.bc") 
print files # ['file1.bc', 'file2.bc'] 

này sẽ được nhanh hơn (không có quá trình khởi động overhead), đáng tin cậy hơn và nền tảng chéo (không phụ thuộc vào nền tảng có một lệnh ls)

+0

'subprocess không gửi lệnh của bạn thông qua một shell' Tại sao? Bạn có thể cung cấp bất kỳ tham chiếu nào không? Cảm ơn – Stallman

+0

Plus nó cung cấp cho một đối tượng python để làm việc với và thao tác. Đây sẽ là câu trả lời được chọn. Nhiều hơn nữa 'python' thân thiện. – Cyan

Các vấn đề liên quan