簡體   English   中英

Python NamedTemporaryFile-讀取時出現ValueError

[英]Python NamedTemporaryFile - ValueError When Reading

我在用Python寫入NamedTemporaryFile並將其讀回時遇到問題。 該函數通過tftpy將文件下載到臨時文件,進行讀取,對內容進行哈希處理,然后將哈希摘要與原始文件進行比較。 有問題的函數如下:

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出錯。 由於with塊未完成,因此我在努力理解為什么將關閉臨時文件。 我能想到的唯一可能性是tftpy在完成下載后正在關閉文件,但是我無法在tftpy源代碼中找到發生這種情況的任何地方。 注意,我也嘗試插入tempfile.seek(0) ,以將文件放回適當的狀態以進行讀取,但是,這也給了我ValueError

tftpy是否可能關閉文件? 我讀到NamedTemporaryFile中可能存在一個錯誤導致此問題? 為什么在with塊定義的引用超出范圍之前關閉文件?

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關閉文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM