之所以会纠结到这个问题上是因为发现在调用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/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 调用结束。可以看到正确的 startend 输出;然后测试比 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.

最新文章

  1. display inline-block 垂直居中
  2. matlab工具箱之人眼检测+meanshift跟踪算法--人眼跟踪
  3. Vuejs使用笔记 --- component内部实现
  4. 常用的winform属性和工具箱工具
  5. 关于迭代器中IEnumerable与IEnumerator的区别
  6. PHPExcel导出导入excel、csv等格式数据
  7. android对app代码混淆
  8. 自己实现的一个简单的EF框架(反射实现)
  9. 【3】Asp.Net Core2.2新版管道处理模型
  10. JavaScript 特效之四大家族(offset/scroll/client/event)
  11. Gatling实战(一)
  12. WinterAndSnowmen
  13. CNCF CloudNative Landscape
  14. 【2019年03月29日】股票的滚动市盈率PE最低排名
  15. Inside The C++ Object Model(五)
  16. exception is java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make su re that file is correct.
  17. django生命周期和事件委派
  18. 高性能mysql之慎用BLOB与TEXT
  19. Intellij下Jquery中文乱码
  20. Qt 查询字符串数据

热门文章

  1. 【干货分享】流程DEMO-借款申请
  2. Android——eclipse下运行android项目报错 Conversion to Dalvik format failed with error 1解决
  3. 在禅道中实现WORD等OFFICE文档转换为PDF进行在线浏览
  4. windows 部署 git 服务器报 Please make sure you have the correct access rights and the repository exists.错误
  5. Android连接网络打印机进行打印
  6. 为支持ASP.NET5跨平台,Jexus再添新举措
  7. MyBatis4:动态SQL
  8. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
  9. 修改Tomcat响应请求时返回的Server内容
  10. 自定义Sublime Text的图标