2010-02-25 31 views
34

Tôi cần khởi chạy một số quy trình chạy dài với subprocess.Popen và muốn có các số stdoutstderr từ mỗi đường ống tự động để tách các tệp nhật ký. Mỗi quá trình sẽ chạy đồng thời trong vài phút và tôi muốn hai tệp nhật ký (stdoutstderr) cho mỗi quá trình được ghi vào khi các quy trình chạy.đầu ra đường ống của quy trình con.Chọn các tệp

Tôi có cần phải liên tục gọi p.communicate() trên mỗi quá trình trong một vòng lặp để cập nhật mỗi file log, hoặc là có một số cách để gọi ban đầu Popen lệnh để stdoutstderr sẽ tự động được xem trực tiếp để mở xử lý tập tin?

Trả lời

34

mỗi the docs,

stdin, stdout và stderr xác định chương trình thực thi đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và lỗi chuẩn xử lý tệp tương ứng. Giá trị hợp lệ là PIPE, 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, chỉ cần chuyển đối tượng tệp mở để viết dưới dạng đối số được đặt tên stdout=stderr= và bạn sẽ ổn thôi!

+0

Cảm ơn. Tôi có thể đã thề rằng tôi đã thử điều đó trước đây và có một lỗi, nhưng đó chính xác là những gì tôi đã hy vọng sẽ làm việc. –

+0

Điều đó không hiệu quả đối với tôi. Tôi đồng thời chạy hai quy trình và lưu stdout và stderr từ cả hai vào một tệp nhật ký. Nếu đầu ra quá lớn, một trong các quy trình con bị treo; không biết cái nào. Tôi không thể sử dụng định dạng trong nhận xét vì vậy tôi sẽ thêm "câu trả lời" bên dưới. – jasper77

53

Bạn có thể vượt qua stdoutstderr như tham số cho Popen()

subprocess.Popen(self, args, bufsize=0, executable=None, stdin=None, stdout=None, 
       stderr=None, preexec_fn=None, close_fds=False, shell=False, 
       cwd=None, env=None, universal_newlines=False, startupinfo=None, 
       creationflags=0) 

Ví dụ

>>> import subprocess 
>>> with open("stdout.txt","wb") as out, open("stderr.txt","wb") as err: 
... subprocess.Popen("ls",stdout=out,stderr=err) 
... 
<subprocess.Popen object at 0xa3519ec> 
>>> 
+3

Woa! Tôi không có ý tưởng bạn có thể chuỗi 'open's như thế trong một người quản lý ngữ cảnh. #mindblown – hwjp

+0

Không phù hợp với tôi! 'với mở (" server.log "," wb ") như sau: sp.call (server_cmd, stdout = out)' – Ayush

2

Tôi đồng thời chạy hai quy trình con và lưu đầu ra từ cả hai vào một tệp nhật ký duy nhất. Tôi cũng đã xây dựng trong một thời gian chờ để xử lý các quy trình con treo. Khi đầu ra quá lớn, thời gian chờ luôn kích hoạt và không có phần tử nào trong số hai tiến trình con được lưu vào tệp nhật ký. Câu trả lời đặt ra bởi Alex ở trên không giải quyết được.

# Currently open log file. 
log = None 

# If we send stdout to subprocess.PIPE, the tests with lots of output fill up the pipe and 
# make the script hang. So, write the subprocess's stdout directly to the log file. 
def run(cmd, logfile): 
    #print os.getcwd() 
    #print ("Running test: %s" % cmd) 
    global log 
    p = subprocess.Popen(cmd, shell=True, universal_newlines = True, stderr=subprocess.STDOUT, stdout=logfile) 
    log = logfile 
    return p 


# To make a subprocess capable of timing out 
class Alarm(Exception): 
    pass 

def alarm_handler(signum, frame): 
    log.flush() 
    raise Alarm 


#### 
## This function runs a given command with the given flags, and records the 
## results in a log file. 
#### 
def runTest(cmd_path, flags, name): 

    log = open(name, 'w') 

    print >> log, "header" 
    log.flush() 

    cmd1_ret = run(cmd_path + "command1 " + flags, log) 
    log.flush() 
    cmd2_ret = run(cmd_path + "command2", log) 
    #log.flush() 
    sys.stdout.flush() 

    start_timer = time.time() # time how long this took to finish 

    signal.signal(signal.SIGALRM, alarm_handler) 
    signal.alarm(5) #seconds 

    try: 
    cmd1_ret.communicate() 

    except Alarm: 
    print "myScript.py: Oops, taking too long!" 
    kill_string = ("kill -9 %d" % cmd1_ret.pid) 
    os.system(kill_string) 
    kill_string = ("kill -9 %d" % cmd2_ret.pid) 
    os.system(kill_string) 
    #sys.exit() 

    end_timer = time.time() 
    print >> log, "closing message" 

    log.close() 
Các vấn đề liên quan