1. 程式人生 > >Python Popen communicate()和wait()使用上的區別

Python Popen communicate()和wait()使用上的區別

使用 subprocess 模組的 Popen 呼叫外部程式,如果 stdout 或 stderr 引數是 pipe,並且程式輸出超過作業系統的 pipe size時,如果使用 Popen.wait() 方式等待程式結束獲取返回值,會導致死鎖,程式卡在 wait() 呼叫上。
 
ulimit -a 看到的 pipe size 是 4KB,那只是每頁的大小,查詢得知 linux 預設的 pipe size 是 64KB。
 
看例子:
 #!/usr/bin/env python
# coding: utf-8
# [email protected]/04/28

import subprocess

def 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'

# 64KB
test(64 * 1024)

# 64KB + 1B
test(64 * 1024 + 1)
 
首先測試輸出為 64KB 大小的情況。使用 dd 產生了正好 64KB 的標準輸出,由 subprocess.Popen 呼叫,然後使用 wait() 等待 dd 呼叫結束。可以看到正確的 start 和 end 輸出;然後測試比 64KB 多的情況,這種情況下只輸出了 start,也就是說程式執行卡在了 p.wait() 上,程式死鎖。具體輸出如下:
start
end
start
 
那死鎖問題如何避免呢?官方文件裡推薦使用 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 done
subprocess.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 wait
p = 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.

相關推薦

Python Popen communicate()wait()使用區別

使用 subprocess 模組的 Popen 呼叫外部程式,如果 stdout 或 stderr 引數是 pipe,並且程式輸出超過作業系統的 pipe size時,如果使用 Popen.wait() 方式等待程式結束獲取返回值,會導致死鎖,程式卡在 wait() 呼叫上

Python中sort()sorted()的區別

-s 可變對象 傳遞 內置函數 ict pan 16px nbsp lin 1、sort()是可變對象(字典)的方法,無參數,無返回值, sort()會改變可變對象,因此無需返回值。例如: list: 1 >>> a = [4,3,7,8] 2 >

sleepwait區別

毫秒 機制 捕獲 控制 斷線 捕獲異常 程序 rup 同步 Java中的多線程是一種搶占式的機制,而不是分時機制。搶占式的機制是有多個線程處於可運行狀態,但是只有一個線程在運行。 共同點 : 1. 他們都是在多線程的環境下,都可以在程序的調用處阻塞指定的毫秒數,並返回。 2

多線程中sleepwait區別,以及多線程的實現方式及原因,定時器--Timer

守護 驗證 取消 技術 方法 代碼 安全 接口 art 1. Java中sleep和wait的區別 ① 這兩個方法來自不同的類分別是,sleep來自Thread類,和wait來自Object類。 sleep是Thread的靜態類方法,誰調用的誰去睡覺,即使在a線程裏調用b

python中returnprint的區別

bsp 不同 urn text 一是 什麽 cnblogs style c99 之前遇到這個問題,就試著對比幾種不同的結果,總結啦一下return和print的區別。 總結: return的作用之一是返回計算的值print的作用是輸出數據到控制端在第一個結果中什麽都沒

【轉載】C# sleep wait區別

通知 sdn 代碼 blog tool ogr rul smart abs eep和wait都是使線程暫時停止執行的方法,但它們有很大的不同。 1. sleep是線程類Thread 的方法,它是使當前線程暫時睡眠,可以放在任何位置。 而wait,它是使當前線程暫時放棄對象的

Python 中 IteratorIterable的區別

pytho 數據 執行 next 判斷 -h 實現 col http (轉載:http://blog.csdn.net/passionkk/article/details/49929887) Python中 list,truple,str,dict這些都可以被叠代,但他們並

python中%r%s的區別

ould mat mark post inf info repr pan formatter %r用rper()方法處理對象 %s用str()方法處理對象 有些情況下,兩者處理的結果是一樣的,比如說處理int型對象。 例一: print "I am %d years o

java sleepwait區別聯系

mon syn cron lee ava pos div 創建 his 1 object monitor java的每個對象都有一個固有的lock,這個lock就稱為object monitor。 比如method,即方法的方法,它也是有一個monitor。所有,如果一個方

Python 中copydeepcopy的區別

deepcopy 改變 般的 blog 等於 div copy clas 但是 import copy 假設在python中對list的復制 copy稱為淺復制 deepcopy稱為深復制 淺復制和深復制在一般的list中作用是相同的,都是進行一個復制 但是在list嵌套l

python 中ifelif的區別

pre else bsp 判斷 nbsp 優秀 自動 滿足 lse 如果程序中判斷事件很多,全部用if的話,會遍歷整個程序,用elif 程序運行時,只要if或後續某一個elif之一滿足邏輯值為True,則程序執行完對應輸出語句後自動結束該輪if-elif(即不會再去冗余地執

python中的 == is 的區別

-s 對比 不能 -- 其他 ont clas 通過 數字 == 比較的是兩邊的值 is 比較的是兩邊的內存地址 通過 id()獲取內存地址 小數據池:我們使用過的值存儲在小數據池中,供其他數據使用.   小數據池僅限於 數字 和 字符串:     數字的小數池範圍 -

博眾娛樂源碼搭建與sleepwait區別

read 如果 運行 inter rup 需要 兩個 sleep bject sleep和wait的區別 1、這兩個方法來自不同的類分別是,sleep來自Thread類,和wait來自Object類。 sleep是Thread的靜態類方法,誰調用的誰去睡覺,(博眾娛樂源碼搭

java中的sleep()wait()的區別

except 的區別 獲取對象 waiting 區別 ace enter thread .html 引自:https://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html 對於sleep()方法,我們首先要知道該方

python題目-----search()match()的區別

match 的區別 成功 ring python spa 查找 none 開始 1. match()函數只檢測re是不是在string的開始位置匹配,也就是說match()只有在0位置匹配成功的話才有返回,如果不是開始位置匹配成功的話,match()就返回none 2. s

python中sysos的區別

move ali 去掉 操作系統 格式 自動 form 出現 class <os和sys的官方解釋> ?os os: This module provides a portable way of using operating system depe

安裝Python之後pip pip3的區別

安裝了python3之後,庫裡面既會有pip3也會有pip  使用pip install XXX  新安裝的庫會放在這個目錄下面  python2.7/site-packages  使用pip3 insta

【轉】【執行緒】sleep() wait() 的區別

https://blog.csdn.net/xyh269/article/details/52613507?utm_source=blogkpcl6   https://blog.csdn.net/lcore/article/details/12221217?utm_source=

Python中*args**kwargs的區別

注:《python核心程式設計第2版》的11.6可變長度的引數—章節中有詳細介紹。 python中我們經常見到,有些函式的引數中有*args和kwargs,那這兩個引數是什麼意思呢? 沒錯,*args和kwargs就是python中的可變引數。 可能很多人用了幾年的 Python 都沒真

Python細說 xrange range 的區別

Python版本2.X: range的返回值是list,這意味著記憶體將會分佈相應的長度的空間給list。 xrange的返回值是一個生成器,有利於節省記憶體空間。 Python版本3.X: 在3.X版本中,Python對range函式做了優化,並且取消了xrange函式。 3.X版本中,range