Python tempfile模块和线程表现不佳;我做错了什么?

2024-10-01 11:25:23 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,线程和tempfile模块有一个有趣的问题。在线程退出之前,某些东西似乎不会被清理干净,而我正在违反打开文件的限制。(这是在OS X 10.5.8和Python 2.5.1上安装的。)

但是如果我复制tempfile模块正在做的事情(不是所有的安全检查,而是生成一个文件描述符,然后使用os.fdopen操作系统产生一个文件对象)我没有问题。在

在把它作为一个bug提交给Python之前,我想我应该在这里检查一下,因为很可能我做了一些微妙的错误。但如果我是的话,一天的努力也没有让我有任何收获。在

#!/usr/bin/python

import threading
import thread
import tempfile
import os
import time
import sys

NUM_THREADS = 10000

def worker_tempfile():
    tempfd, tempfn = tempfile.mkstemp()
    tempobj = os.fdopen(tempfd, 'wb')
    tempobj.write('hello, world')
    tempobj.close()
    os.remove(tempfn)
    time.sleep(10)

def worker_notempfile(index):
    tempfn = str(index) + '.txt'
    # The values I'm passing os.open may be different than tempfile.mkstemp 
    # uses, but it works this way as does using the open() function to create
    # a file object directly.
    tempfd = os.open(tempfn, 
                     os.O_EXCL | os.O_CREAT | os.O_TRUNC | os.O_RDWR)
    tempobj = os.fdopen(tempfd, 'wb')
    tempobj.write('hello, world')
    tempobj.close()
    os.remove(tempfn)
    time.sleep(10)

def main():
    for count in range(NUM_THREADS):
        if count % 100 == 0:
            print('Opening thread %s' % count)
        wthread = threading.Thread(target=worker_tempfile)
        #wthread = threading.Thread(target=worker_notempfile, args=(count,))
        started = False
        while not started:
            try:
                wthread.start()
                started = True
            except thread.error:
                print('failed starting thread %s; sleeping' % count)
                time.sleep(3)

if __name__ == '__main__':
    main()

如果我在worker_notempfile行处于活动状态并且worker_tempfile行被注释掉的情况下运行它,它将运行到完成状态。在

另一种方法(使用worker_tempfile)得到以下错误:

^{pr2}$

你知道我做错了什么吗?这是Python中的一个bug,还是我有点头晕目眩?在

更新2009年12月14日: 我想我找到了答案,但我不喜欢。因为没人能复制这个问题,我就到处找机器。除了我的机器什么都没用。我在一台Mac电脑上测试了我使用的软件版本。我甚至去寻找一个桌面G5,它的硬件和软件配置和我完全一样——结果是一样的。两个测试(有tempfile和没有tempfile)都成功了。在

为了获得成功,我下载了Python2.6.4,并在桌面上进行了尝试,在我的系统上使用了与Python2.5.1相同的模式:tempfile失败,notempfile成功。在

这让我得出结论:我的Mac电脑上有东西,但我肯定搞不清是什么。欢迎提出任何建议。在


Tags: 文件importtimeosdefcounttempfilethread
3条回答

我无法在MacOSX10.5.9上用(苹果自己构建的)Python2.5.1来重现这个问题——运行起来很好!在

我在MacBookPro(即英特尔处理器)和旧PowerMac(即PPC处理器)上都试过。在

所以我只能想象在10.5.8中一定有一个我从未注意到的bug(没有任何10.5.8可以测试,因为每当软件更新提供时,我总是迅速升级)。我只能建议你升级到10.5.9版本,看看这个bug是否消失了——如果没有,我不知道我的机器和你的机器之间的行为差异是怎么可能的。在

我想你的答案可以找到。您必须显式地os.close()作为mkstemp提供的元组的第一部分给出的文件描述符。在

编辑:不,手术室已经在做该做的事了。我把答案留到好的链接上。在

我刚刚在我的Ubuntu Linux电脑上测试了你的代码,它对我来说非常好。在

我有一个建议你试试。我不知道这会不会有帮助,但不会受伤。重写代码以用于:

from __future__ import with_statement

def worker_tempfile():
    tempfd, tempfn = tempfile.mkstemp()
    with os.fdopen(tempfd, 'wb') as tempobj:
        tempobj.write('hello, world')
    os.remove(tempfn)
    time.sleep(10)

with语句应该确保无论发生什么情况,file对象都会被关闭。也许会有帮助?在

祝你好运。顺便问一句,很好。在

相关问题 更多 >