简体   繁体   English

Python NamedTemporaryFile-读取时出现ValueError

[英]Python NamedTemporaryFile - ValueError When Reading

I am having an issue writing to a NamedTemporaryFile in Python and then reading it back. 我在用Python写入NamedTemporaryFile并将其读回时遇到问题。 The function downloads a file via tftpy to the temp file, reads it, hashes the contents, and then compares the hash digest to the original file. 该函数通过tftpy将文件下载到临时文件,进行读取,对内容进行哈希处理,然后将哈希摘要与原始文件进行比较。 The function in question is below: 有问题的函数如下:

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

The problem is that every time I try to execute the line uploaded_digest = hashlib.sha256(tempfile.read()).hexdigest() the application errors out with a ValueError - I/O Operation on a closed file . 问题是每次我尝试执行该行uploaded_digest = hashlib.sha256(tempfile.read()).hexdigest() ,应用程序都会ValueError - I/O Operation on a closed file出错。 Since the with block is not complete I am struggling to understand why the temp file would be closed. 由于with块未完成,因此我在努力理解为什么将关闭临时文件。 The only possibility I can think of is that tftpy is closing the file after doing the download, but I cannot find any point in the tftpy source where this would be happening. 我能想到的唯一可能性是tftpy在完成下载后正在关闭文件,但是我无法在tftpy源代码中找到发生这种情况的任何地方。 Note, I have also tried inserting the line tempfile.seek(0) in order to put the file back in a proper state for reading, however this also gives me the ValueError . 注意,我也尝试插入tempfile.seek(0) ,以将文件放回适当的状态以进行读取,但是,这也给了我ValueError

Is tftpy closing the file possibly? tftpy是否可能关闭文件? I read that there is possibly a bug in NamedTemporaryFile causing this problem? 我读到NamedTemporaryFile中可能存在一个错误导致此问题? Why is the file closed before the reference defined by the with block goes out of scope? 为什么在with块定义的引用超出范围之前关闭文件?

TFTPy is closing the file. TFTPy正在关闭文件。 When you were looking at the source, you missed the following code path: 在查看源代码时,您错过了以下代码路径:

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 calls TftpContextClientDownload.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 calls TftpContext.end : 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()  # <--

and TftpContext.end closes the file. 然后TftpContext.end关闭文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM