Python NamedTemporaryFile - 读取时的ValueError

时间:2016-07-19 17:56:51

标签: python temporary-files tftp hashlib

我在使用Python写入NamedTemporaryFile时遇到了问题,然后将其读回来。该函数通过tftpy将文件下载到临时文件,读取它,散列内容,然后将散列摘要与原始文件进行比较。有问题的功能如下:

arr[4][3][5] = 4

问题在于,每当我尝试使用def verify_upload(self, image, destination): # create a tftp client client = TftpClient(ip, 69, localip=self.binding_ip) # generate a temp file to hold the download info if not os.path.exists("temp"): os.makedirs("temp") with NamedTemporaryFile(dir="temp") as tempfile, open(image, 'r') as original: try: # attempt to download the target image client.download(destination, tempfile, timeout=self.download_timeout) except TftpTimeout: raise RuntimeError("Could not download {0} from {1} for verification".format(destination, self.target_ip)) # hash the original file and the downloaded version original_digest = hashlib.sha256(original.read()).hexdigest() uploaded_digest = hashlib.sha256(tempfile.read()).hexdigest() if self.verbose: print "Original SHA-256: {0}\nUploaded SHA-256: {1}".format(original_digest, uploaded_digest) # return the hash comparison return original_digest == uploaded_digest 执行行uploaded_digest = hashlib.sha256(tempfile.read()).hexdigest()时,应用程序出错。由于ValueError - I/O Operation on a closed file块未完成,我很难理解为什么临时文件将被关闭。我能想到的唯一可能性是tftpy在下载后关闭了文件,但我找不到tftpy源中发生这种情况的任何一点。请注意,我还尝试插入行with以便将文件重新置于适当的状态以便阅读,但这也为tempfile.seek(0)提供了信息。

tftpy可能关闭文件吗?我读到NamedTemporaryFile中可能存在一个导致此问题的错误?为什么在ValueError块定义的引用超出范围之前文件已关闭?

1 个答案:

答案 0 :(得分:2)

TFTPy正在关闭该文件。当您查看源代码时,您错过了以下代码路径:

class TftpClient(TftpSession):
    ...
    def download(self, filename, output, packethook=None, timeout=SOCK_TIMEOUT):
        ...
        self.context = TftpContextClientDownload(self.host,
                                                 self.iport,
                                                 filename,
                                                 output,
                                                 self.options,
                                                 packethook,
                                                 timeout,
                                                 localip = self.localip)
        self.context.start()
        # Download happens here
        self.context.end()  # <--

TftpClient.download来电TftpContextClientDownload.end

class TftpContextClientDownload(TftpContext):
    ...
    def end(self):
        """Finish up the context."""
        TftpContext.end(self)  # <--
        self.metrics.end_time = time.time()
        log.debug("Set metrics.end_time to %s", self.metrics.end_time)
        self.metrics.compute()

TftpContextClientDownload.end来电TftpContext.end

class TftpContext(object):
    ...
    def end(self):
        """Perform session cleanup, since the end method should always be
        called explicitely by the calling code, this works better than the
        destructor."""
        log.debug("in TftpContext.end")
        self.sock.close()
        if self.fileobj is not None and not self.fileobj.closed:
            log.debug("self.fileobj is open - closing")
            self.fileobj.close()  # <--

TftpContext.end关闭文件。