2012-11-15 39 views
16

Vì vậy, tôi nhận thấy subprocess.call trong khi chờ lệnh kết thúc trước khi tiếp tục với tập lệnh python, tôi không có cách nào để lấy giá trị stdout, ngoại trừ subprocess.Popen. Có bất kỳ cuộc gọi chức năng thay thế nào sẽ đợi cho đến khi nó kết thúc? (Tôi cũng đã cố gắng Popen.wait)Python subprocess.call và subprocess.Popen stdout

Chú ý: Tôi đang cố gắng để tránh os.system gọi

result = subprocess.Popen([commands..., 
         self.tmpfile.path()], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
out, err = result.communicate() 
print out+"HIHIHI" 

đầu ra của tôi:

HIHIHI 

LƯU Ý: Tôi cố gắng để chạy wine với điều này.

+1

* subprocess.call() * có thể được sử dụng để đọc/lỗi. [vui lòng kiểm tra hướng dẫn] (http://docs.python.org/2/library/subprocess.html). đảm bảo lệnh không tạo ra nhiều đầu ra. – tuxuday

Trả lời

46

Tôi đang sử dụng cấu trúc sau, mặc dù bạn có thể muốn tránh shell=True. Điều này sẽ cho bạn những kết quả và thông báo lỗi cho bất kỳ lệnh, và mã lỗi cũng như:

process = subprocess.Popen(cmd, shell=True, 
          stdout=subprocess.PIPE, 
          stderr=subprocess.PIPE) 

# wait for the process to terminate 
out, err = process.communicate() 
errcode = process.returncode 
+0

Tôi đã thử điều này và tôi vẫn nhận được kết quả trống: không hoàn toàn chắc chắn những gì tôi đang làm sai. –

+2

Nội dung của 'cmd' là gì? – Alex

+0

@Alex cmd phải là lệnh bạn muốn thực hiện. – NeoMorfeo

10

Nếu quá trình của bạn đưa ra một stdout khổng lồ và không stderr, communicate() có thể là cách sai lầm khi đi do hạn chế bộ nhớ.

Thay vào đó,

process = subprocess.Popen(cmd, shell=True, 
          stdout=subprocess.PIPE, 
          stderr=subprocess.PIPE) 

# wait for the process to terminate 
for line in process.stdout: do_something(line) 
errcode = process.returncode 

có thể là cách để đi.

process.stdout là một đối tượng tập tin giống như mà bạn có thể coi như bất kỳ đối tượng nào khác, chủ yếu là:

  • bạn có thể read() từ nó
  • bạn có thể readline() từ nó và
  • bạn có thể duyệt qua nó.

Sau đó là những gì tôi làm ở trên để có được nội dung của nó theo từng dòng.

+1

Bạn có thể giải thích cho tôi về vòng lặp for không? –

+0

@ Stupid.Fat.Cat Nó đọc 'stdout' được tạo ra từ dòng xử lý theo từng dòng và xử lý từng dòng. – glglgl

+0

Tôi nhận được 'ValueError: I/O hoạt động trên tập tin đóng' cho hoạt động' cho dòng trong process.stdout' – Yash89

11
subprocess.check_output(...) 

gọi quá trình này, tăng nếu mã lỗi của nó không đồng bộ và trả về giá trị khác. Nó chỉ là một cách viết tắt nhanh chóng, do đó bạn không cần phải lo lắng về các số PIPE và mọi thứ.

+0

Điều này có vấn đề với 'rượu vang' tôi tin. Xin lỗi, tôi sẽ thêm nó vào câu hỏi của tôi. –

+3

Đây là một tính năng tuyệt vời, chỉ trong Python 2.7 hoặc mới hơn. – Gourneau

1

Tôi muốn thử một cái gì đó như:

#!/usr/bin/python 
from __future__ import print_function 

import shlex 
from subprocess import Popen, PIPE 

def shlep(cmd): 
    '''shlex split and popen 
    ''' 
    parsed_cmd = shlex.split(cmd) 
    ## if parsed_cmd[0] not in approved_commands: 
    ## raise ValueError, "Bad User! No output for you!" 
    proc = Popen(parsed_command, stdout=PIPE, stderr=PIPE) 
    out, err = proc.communicate() 
    return (proc.returncode, out, err) 

... Nói cách khác chúng ta hãy shlex.split() làm hầu hết công việc. Tôi sẽ không cố gắng phân tích cú pháp dòng lệnh của trình bao, tìm các toán tử đường ống và thiết lập đường dẫn của riêng bạn. Nếu bạn định làm điều đó thì về cơ bản bạn sẽ phải viết một trình phân tích cú pháp cú pháp trình bao (shell parser) hoàn chỉnh và cuối cùng bạn sẽ làm rất nhiều hệ thống ống nước.

Tất nhiên điều này đặt ra câu hỏi, tại sao không chỉ sử dụng Popen với tùy chọn shell = True (từ khóa)? Điều này sẽ cho phép bạn vượt qua một chuỗi (không tách và phân tích cú pháp) cho trình bao và vẫn thu thập kết quả để xử lý như bạn muốn. Ví dụ của tôi ở đây sẽ không xử lý bất kỳ đường ống, backticks, chuyển hướng mô tả tập tin, vv có thể có trong lệnh, tất cả chúng sẽ xuất hiện dưới dạng đối số theo nghĩa đen cho lệnh. Do đó, nó vẫn an toàn hơn khi chạy với shell = True ...Tôi đã đưa ra một ví dụ ngớ ngẩn về việc kiểm tra lệnh chống lại một số từ điển "lệnh được chấp thuận" hoặc đặt --- thông qua nó sẽ có ý nghĩa hơn để bình thường hóa nó thành một đường dẫn tuyệt đối trừ khi bạn có ý định yêu cầu các đối số được chuẩn hóa trước chuyển chuỗi lệnh đến hàm này.

+0

Tôi thích ví dụ này, chú ý đến shlex như là một cách thích hợp để phân tích đầu vào dòng lệnh. Hài hước trong ví dụ, quá (shlep() và ý kiến ​​ngoại lệ). :) –

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