2013-02-06 35 views
9

Tôi đang gọi một chương trình java từ kịch bản Python của tôi, và nó xuất ra rất nhiều thông tin vô dụng mà tôi không muốn. Tôi đã thử addind stdout=None với chức năng Popen:Bỏ qua đầu ra từ subprocess.Popen

subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None) 

Nhưng cũng vậy. Bất kỳ ý tưởng?

Trả lời

31

Từ 3.3 documentation:

stdin, stdout và stderr định đầu vào tiêu chuẩn chương trình thực thi của tiêu chuẩn đầu ra và xử lý tập tin lỗi chuẩn, tương ứng. Các giá trị hợp lệ là PIPE, DEVNULL, một bộ mô tả tệp hiện có (một số nguyên dương), một đối tượng tệp hiện có và Không có.

Vì vậy:

subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=subprocess.DEVNULL) 

này chỉ tồn tại trong 3.3 và sau này. Nhưng tài liệu cho biết:

DEVNULL cho biết tệp đặc biệt os.devnull sẽ được sử dụng.

os.devnull tồn tại cách quay lại 2.4 (trước khi subprocess tồn tại). Vì vậy, bạn có thể làm điều tương tự bằng tay:

with open(os.devnull, 'w') as devnull: 
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull) 

Lưu ý rằng nếu bạn đang làm một cái gì đó phức tạp hơn mà không phù hợp với một dòng duy nhất, bạn cần phải giữ devnull mở cho toàn bộ cuộc sống của Popen đối tượng, không chỉ xây dựng. (Nghĩa là, hãy đặt toàn bộ nội dung bên trong câu lệnh with.)

Lợi thế của việc chuyển hướng đến /dev/null (POS) hoặc bạn không tạo ra một đường ống không cần thiết và quan trọng hơn là có thể ' t chạy vào các trường hợp cạnh mà các khối con xử lý trên văn bản cho đường ống đó.

Điểm bất lợi là, theo lý thuyết, subprocess có thể hoạt động trên một số nền tảng mà os.devnull thì không. Nếu bạn chỉ quan tâm đến CPython trên POSIX và Windows, PyPy và Jython (phần lớn bạn), điều này sẽ không bao giờ là vấn đề. Đối với các trường hợp khác, hãy kiểm tra trước khi phân phối mã của bạn.

+0

+1: cho devnull. Hãy chắc chắn rằng 'devnull' vẫn mở trong khi tiến trình con còn sống (câu lệnh có ngụ ý khác). Đoạn cuối cùng có vẻ không cần thiết: DEVNULL được triển khai thông qua os.devnull trong CPython. os.devnull làm việc với Jython. – jfs

+0

@ J.F.Sebastian: Sau 'check_call' (nằm bên trong' with'), 'devnull' không còn cần thiết nữa. Nhưng vâng, có lẽ tôi nên làm rõ rằng đối với các trường hợp sử dụng phức tạp hơn mà không phù hợp với một dòng, toàn bộ điều cần phải ở bên trong 'with', không chỉ là' Popen'. – abarnert

+0

@JFSebastian: Trong khi đó, đối với 'os.devnull', nó thực sự được bảo đảm tồn tại trên mọi nền tảng mà' xử lý con 'tồn tại, vì vậy không cần phải "kiểm tra trước khi sử dụng", hay bạn chỉ biết rằng nó cũng tồn tại trên Jython và do đó tôi nên di chuyển Jython vào danh sách các nền tảng mà bạn không cần phải kiểm tra? – abarnert

6

Từ documentation:

Với các thiết lập mặc định của None, không chuyển hướng sẽ xảy ra.

Bạn cần phải thiết lập stdout-subprocess.PIPE, sau đó gọi .communicate() và chỉ đơn giản là bỏ qua các đầu ra chụp.

p = subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE) 
p.communicate() 

mặc dù tôi nghi ngờ rằng việc sử dụng subprocess.call() hơn đủ cho nhu cầu của bạn:

subprocess.call(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE) 
+1

@sjtaheri: cảm ơn vì đã sửa, tôi đã tự áp dụng nó. –

+4

Tạo và bỏ qua một đường ống thường hoạt động, nhưng nó có thể dẫn đến quá trình chặn con nếu nó viết quá nhiều (và dĩ nhiên nó có thể hoạt động trên hệ thống của bạn và thất bại cho một trong những người dùng của bạn), vì vậy tôi nghĩ nó thực sự không phải là ' t an toàn để chỉ 'gọi' ở đây thay vì' giao tiếp'. Đó là lý do tại sao 'DEVNULL' được thêm vào - vì vậy bạn _can_ chỉ' gọi' và không lo lắng về nó. (Vâng, nó có cho trường hợp hơi phức tạp hơn, nơi bạn đặt 'stderr = DEVNULL' nhưng không' stdout', và chỉ 'check_output'. Nhưng cùng một ý tưởng.) – abarnert

+0

@abarnert: Ah, không biết rằng đã được thêm vào ; chỉ tìm thấy nó trong tài liệu Python 3. –

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