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
calls 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
:
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
关闭文件。
我在写入 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
calls 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
:
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
关闭文件。