当我在多线程中使用 #Fabric put# 将 tempfile.mkstemp 创建的临时文件复制到远程文件时找不到文件

Posted

技术标签:

【中文标题】当我在多线程中使用 #Fabric put# 将 tempfile.mkstemp 创建的临时文件复制到远程文件时找不到文件【英文标题】:File cannot be found when i use #Fabric put# in multi-threading to copy a temp file created by tempfile.mkstemp to a remote file 【发布时间】:2014-06-30 11:09:14 【问题描述】:

Python 版本:2.6.4

Fabric 版本:1.9.0

我有一个自动化测试框架,可以使用 threading.Thread(在我的案例中为 3 个线程)并行执行案例。

每个线程工作者都使用fabric put(我们在这个函数上做了一些包装)将由tempfile.mkstemp创建的临时文件复制到远程文件。

问题是它总是给我一个找不到文件的错误,错误发生在异常提示的“放置”期间。

这里是执行'put'时的代码:

MyShell.py(MyFabShell 的父类)

def putFileContents(self, file, contents):

    fd, tmpFile= tempfile.mkstemp()

    os.system('chmod 777 %s' % tmpFile)

    contentsFile = open(tmpFile, 'w')
    contentsFile.write(contents)
    contentsFile.close()

    dstTmpFile = self.genTempFile()

    localshell = getLocalShell()

    self.get(localshell, tmpFile, dstTmpFile) # use local shell to put tmpFile to dstTmpFile


    os.close(fd)

    os.remove(tmpFile)
    #os.remove(tmpFile)

MyFabShell.py:

def get( self, srcShell, srcPath, dstPath ):
    srcShell.put( self, srcPath, dstPath )

def put(self, dstShell, srcpath, dstpath):

    if not self.pathExists( srcPath ):  # line 158
        raise Exception( "Cannot put <%s>, does not exist." % srcPath )

    # do fabric get/put in the following
    # ...

put的调用报错:

...
self.shell.putFileContents(configFile, contents)
File "/path/to/MyShell.py", line 401, in putFileContents
self.get(localShell, tmpFile, dstTmpFile)
File "/path/to/MyFabShell.py", line 134, in get
srcShell.put( self, srcPath, dstPath )
File "/path/to/myFabShell.py", line 158, in put
raise Exception( "Cannot put <%s>, does not exist." % srcPath )
Exception: Cannot put </tmp/tmpwt3hoO>, does not exist.

我最初怀疑文件是否可以在put 期间被删除,所以我评论了os.remove。但是,我又遇到了同样的错误。 从异常日志来看,应该不是“fabric put”的问题,因为在执行fabric get/put之前抛出异常 涉及多线程时mkstemp 不安全吗?但是文件说“文件的创建没有竞争条件”或者我的案例是否因为 GIL 而失败?我怀疑这是因为当我只使用 1 个线程时,一切都会好起来的。

谁能给我一些关于我的错误的线索?我已经为这个问题苦苦挣扎了一段时间:(

【问题讨论】:

线程什么时候发生?这段代码是否已经在线程中,或者是否发生在 myput 中?您还可以提供堆栈跟踪吗?和/或您的包装器中发生了什么的一般概念? 谢谢@Morgan,我已经用模式代码和日志详细说明了我的问题。 当我明确地“加入”线程时,我的问题就解决了。我所有的线程都不是守护线程,每个线程都有相当多的 I/O 操作(例如文件写入/读取)。 'join' 显式将确保每个线程的工作都已完成。我仍然不确定我的问题的根本原因......临时文件实际上存在但线程抱怨“找不到”,我唯一能给出的猜测是我们应该始终明确加入,特别是当你的线程工作涉及我时/O 操作? 【参考方案1】:

当我明确地“加入”线程时,我的问题就解决了。我所有的线程都不是守护线程,每个线程都有相当多的 I/O 操作(例如文件写入/读取)。 'join' 显式将确保每个线程的工作都已完成。 我仍然不确定我的问题的根本原因......临时文件实际上在那里但是当多个线程一起工作时线程抱怨“找不到”,我能给出的唯一猜测是: 当线程 A 进行 I/O 操作时,线程 A 将释放 GIL,以便线程 B(或 C、D...)可以在 A 的 I/O 操作时间内获取 GIL。问题可能发生在 I/O 期间,因为线程 A 不再在 Python 解释器中......这就是 A “找不到文件”的原因,但是,当我们显式加入 A 时,A 将始终确保通过重新进入 GI(Global Interpreter) 完成其工作。

【讨论】:

以上是关于当我在多线程中使用 #Fabric put# 将 tempfile.mkstemp 创建的临时文件复制到远程文件时找不到文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Fabric将目录复制到远程计算机?

在多线程崩溃的 MFC 中使用 Techart activeX

在多线程环境中更新 DataGrid 视图

程序在多线程中没有顺利结束

在多线程 Rails 环境中使用 Redis 的最佳方式是啥? (彪马/Sidekiq)

在多线程程序中使用 Executer 服务