2012-07-15 40 views
24

Tôi muốn chuyển hướng đầu ra stderr của một tiến trình con tới stdout. Các hằng số STDOUT nên làm điều đó, phải không?Chuyển hướng stderr phụ tiến trình tới stdout

Tuy nhiên,

$ python >/dev/null -c 'import subprocess;\ 
         subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)' 

không ra một cái gì đó. Tại sao lại là trường hợp đó và làm thế nào để tôi nhận được thông báo lỗi trên stdout?

+0

BTW, được cố định ở trăn 3.5. – max

Trả lời

29

Đọc gần source code cho câu trả lời. Đặc biệt, documentation được gây hiểu lầm khi nó nói:

subprocess.STDOUT
giá trị đặc biệt đó (...) chỉ ra rằng sai số chuẩn nên đi vào cùng xử lý như đầu ra tiêu chuẩn.

Kể từ stdout được thiết lập để "mặc định" (-1, về mặt kỹ thuật) khi stderr=subprocess.STDOUT được đánh giá, stderr được thiết lập để "mặc định" là tốt. Thật không may, điều này có nghĩa rằng đầu ra stderr vẫn đi đến stderr.

Để giải quyết vấn đề, vượt qua trong các tập tin stdout thay vì subprocess.STDOUT:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.buffer)' 

Hoặc, để tương thích với các phiên bản di sản 2.x của Python:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.fileno())' 
+0

Người ta cũng có thể để lại stderr như là: 'stderr = sys.stderr.fileno()'. Ví dụ điển hình; Tôi sẽ sử dụng kỹ thuật này trong tất cả các kịch bản của mình. Chúng ta có Python 2.x; do đó tôi sẽ biết chính xác nơi tôi bảo nó đi mà không nhầm lẫn. –

6

Trên thực tế, sử dụng không subprocess.STDOUTchính xác nội dung được nêu trong tài liệu: nó chuyển hướng stderr sang stdout để ví dụ

proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
output = "" 
while (True): 
    # Read line from stdout, break if EOF reached, append line to output 
    line = proc.stdout.readline() 
    line = line.decode() 
    if (line == ""): break 
    output += line 

kết quả trong đầu ra có chứa quá trình 'đầu ra từ cả stdout và stderr.

stderr=subprocess.STDOUT chuyển hướng tất cả đầu ra stderr trực tiếp để thoát khỏi quá trình gọi, đó là sự khác biệt lớn.

+0

-1 Trường hợp này không liên quan đến câu hỏi về 'stdout' là' None'. Và 'subprocess.STDOUT' không chuyển hướng đến" bàn điều khiển gọi "(tôi nghĩ bạn có nghĩa là tập tin xử lý 1 mà quá trình hiện tại đã được đưa ra), như ví dụ của bạn cho thấy - nếu bạn gọi Popen với' ['ls', '/404 '] ', [thông báo lỗi không được hiển thị] (http://ideone.com/2JhcRT). – phihag

+0

Bạn có phần đúng. Tuy nhiên, tôi không nghĩ rằng điều này là không thích hợp ở tất cả, vì điều này là nhằm làm rõ bài viết của bạn liên quan đến các tài liệu được gây hiểu lầm - đó không phải là trường hợp. Tôi đã để lại một bình luận bên dưới bài viết của bạn, nhưng một năm trước, tôi đã không được phép làm như vậy. – Maxxim

+0

'python -c 'nhập subprocess, sys; subprocess.call ([" ls ","/404 "], stderr = subprocess.STDOUT)' 2>/dev/null' cho thấy rằng stderr của' ls' chuyển đến stderr (bộ mô tả tập tin 2) vì bạn sẽ không thấy bất kỳ đầu ra nào (giả sử bạn không có '/ 404' trên hệ thống của bạn). Đó là tài liệu Python thực sự ngửi về chủ đề đó, và nó đặc biệt gây phiền toái cho chúng tôi shell scripters được sử dụng để thao tác stdout/stderr trong vô số cách, và phải đến đây để SO chỉ để tìm ra cách để làm điều gì đó đơn giản và không gây nhầm lẫn. –

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