我在使用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
块定义的引用超出范围之前文件已关闭?
答案 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
关闭文件。