Python subprocess.Popen communicate() 和wait()使用上的區別,pythonpopenwait

來源:互聯網
上載者:User

Python subprocess.Popen communicate() 和wait()使用上的區別,pythonpopenwait

之所以會糾結到這個問題上是因為發現在調用Popen的wait方法之後程式一直沒有返回。google發現wait是有可能產生死結的。為了把這個問題徹底弄清楚,搜尋一些資料過來看看:

原文連結:http://blog.csdn.net/carolzhang8406/article/details/22286913

看到別人的例子:

今天遇到的一個問題。簡單說就是,使用 subprocess 模組的 Popen 調用外部程式,如果 stdoutstderr 參數是 pipe,並且程式輸出超過作業系統的 pipe size時,如果使用 Popen.wait() 方式等待程式結束擷取傳回值,會導致死結,程式卡在 wait() 調用上。

ulimit -a 看到的 pipe size 是 4KB,那隻是每頁的大小,查詢得知 linux 預設的 pipe size 是 64KB。

看例子:

#!/usr/bin/env python# coding: utf-8# yc@2013/04/28import subprocessdef test(size):    print 'start'    cmd = 'dd if=/dev/urandom bs=1 count=%d 2>/dev/null' % size    p = subprocess.Popen(args=cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)    #p.communicate()    p.wait()    print 'end'# 64KBtest(64 * 1024)# 64KB + 1Btest(64 * 1024 + 1)

首先測試輸出為 64KB 大小的情況。使用 dd 產生了正好 64KB 的標準輸出,由 subprocess.Popen 調用,然後使用 wait() 等待 dd 調用結束。可以看到正確的 startend 輸出;然後測試比 64KB 多的情況,這種情況下只輸出了 start,也就是說程式執行卡在了 p.wait() 上,程式死結。具體輸出如下:

startendstart

那死結問題如何避免呢?官方文檔裡推薦使用 Popen.communicate()。這個方法會把輸出放在記憶體,而不是管道裡,所以這時候上限就和記憶體大小有關了,一般不會有問題。而且如果要獲得程式傳回值,可以在調用 Popen.communicate() 之後取 Popen.returncode 的值。

結論:如果使用 subprocess.Popen,就不使用 Popen.wait(),而使用 Popen.communicate() 來等待外部程式執行結束。

Popen.wait()¶

Wait for child process to terminate.  Set and returnreturncode attribute.

Warning

This will deadlock when using stdout=PIPE and/orstderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data.  Use communicate() to avoid that.

Popen.communicate( input=None

Interact with process: Send data to stdin.  Read data from stdout and stderr, until end-of-file is reached.  Wait for process to terminate. The optionalinput argument should be a string to be sent to the child process, orNone, if no data should be sent to the child.

communicate() returns a tuple (stdoutdata, stderrdata).

Note that if you want to send data to the process’s stdin, you need to create the Popen object with stdin=PIPE.  Similarly, to get anything other thanNone in the result tuple, you need to give stdout=PIPE and/orstderr=PIPE too.

Note

The data read is buffered in memory, so do not use this method if the data size is large or unlimited.

subprocess 的兩種方法:

1)如果想調用之後直接阻塞到子程式調用結束:

Depending on how you want to work your script you have two options. If you want the commands to block and not do anything while it is executing, you can just use subprocess.call.

#start and block until donesubprocess.call([data["om_points"], ">", diz['d']+"/points.xml"])


2)非阻塞的時候方式:

If you want to do things while it is executing or feed things into stdin, you can use communicate after the popen call.

#start and process things, then waitp = subprocess.Popen(([data["om_points"], ">", diz['d']+"/points.xml"])print "Happens while running"p.communicate() #now wait

As stated in the documentation, wait can deadlock, so communicate is advisable.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.