我在python中打开/关闭文件时遇到了这个奇怪的问题。我正在尝试在python中做与在matlab中成功完成的相同的事情,但是在通过文本文件与某些软件进行通讯时遇到了问题。我想出了一个奇怪的解决方法来解决该问题,但是我不明白为什么会起作用。
我有与某些实验室设备通讯的软件。为了与此软件进行通信,我将文件('wavefile.txt')写入特定的文件夹,其中包含要发送到设备的参数。然后,我写另一个名为“ request.txt”的文件,其中包含第一个文件(“ wavefile.txt”)的位置,该文件包含要发送到设备的参数。软件会不断检查此文件夹以找到名为“ request.txt”的文件,一旦找到该文件,它将读取文件中“ request.txt”中文本指定的参数,然后删除“ request.txt” '。软件/设备开发人员指示在关闭“ request.txt”文件之前给出50毫秒的延迟。
有效的原始matlab代码:
home = cd;
cd \\CREOL-FAST-01\data
fileID = fopen('request.txt', 'wt');
proj = 'C:\\dazzler\\data\\wavefile.txt';
fprintf(fileID, proj);
pause(0.05);
fclose('all');
cd(home);
无效的原始python代码:
home = os.getcwd()
os.chdir(r'\\CREOL-FAST-01\data')
with open('request.txt', 'w') as file:
proj = r'C:\dazzler\data\wavefile.txt'
file.write(proj)
time.sleep(0.05)
os.chdir(home)
每次设备程序在使用matlab时读取“ request.txt”时,都会在matlab关闭后立即将其删除。当我使用python运行该代码时,它可能会在某些时候运行,也许每5次尝试中就有1次将成功执行并发送参数。 “ request.txt”文件始终使用上面的python代码删除,但是我输入的参数显然不会发送到我的实验室设备。我的猜测是,当我用python编写文件时,设备程序能够在python将文本写入文本之前读取它,因此它只是打开空白文件,不应用任何参数,然后将其删除。
我在python中的解决方法:
home = os.getcwd()
os.chdir(r'\\CREOL-FAST-01\data')
fileh = open('request.txt', 'w+')
proj = r'C:\dazzler\data\wavefile.txt'
fileh.write(proj)
time.sleep(0.05)
print(fileh.read())
time.sleep(0.05)
fileh.close()
此方法在python中似乎可以100%地起作用。我以w +模式打开文件,并且绝对需要使用fileh.read()。如果我删除该行并且仍然包括额外的睡眠时间,它将再次在大约5次尝试中工作1次。这对我来说真的很奇怪。有什么解释或更好的解决方案吗?
答案 0 :(得分:2)
我的猜测(可能是错误的)是在文件完全刷新之前正在读取文件。我会在写入后尝试使用 flush()
方法,以确保将完整的数据写入文件中。您可能还需要os.fsync()
方法来确保正确刷新数据。尝试这样的事情:
home = os.getcwd()
os.chdir(r'\\CREOL-FAST-01\data')
with open('request.txt', 'w') as file:
proj = r'C:\dazzler\data\wavefile.txt'
file.write(proj)
file.flush()
os.fsync()
time.sleep(0.05)
os.chdir(home)
答案 1 :(得分:2)
不知道有关正在使用的特定设备和其他软件的任何详细信息,这很难说。一种猜测是写调用缓冲的区别。
在有关Matlab fwrite的这篇博客文章中:“ fprintf和fwrite的默认行为是在每次调用这两个函数之一后刷新文件缓冲区”
Python open的地方:
不提供缓冲参数时,默认缓冲策略 工作原理如下:
二进制文件以固定大小的块缓冲;缓冲区的大小 选择使用启发式尝试来确定基础 设备的“块大小”,然后返回io.DEFAULT_BUFFER_SIZE。上 在许多系统中,缓冲区的长度通常为4096或8192字节。
“交互式”文本文件(isatty()返回True的文件)使用 行缓冲。其他文本文件将上述策略用于 二进制文件。
要测试此猜测更改,请执行以下操作:
with open('request.txt', 'w') as file:
proj = r'C:\dazzler\data\wavefile.txt'
收件人:
with open('request.txt', 'w', buffer=1) as file:
proj = 'C:\\dazzler\\data\\wavefile.txt\n'
答案 2 :(得分:0)
问题可能出在文件仍处于打开状态,因此未写入磁盘时,您正在延迟。尝试这样的事情:
home = os.getcwd()
os.chdir(r'\\CREOL-FAST-01\data')
with open('request.txt', 'w') as file:
proj = r'C:\dazzler\data\wavefile.txt'
file.write(proj)
time.sleep(0.05)
os.chdir(home)
这里唯一的区别是,在文件关闭后 结束睡眠(with
块结束时文件关闭了),因此延迟不会发生,直到将文本写入磁盘后。
用语言来说,您正在做的是:
您想要做的是:
因此,最终的结果是创建文本文件的时间至少为50毫秒,但是其中没有任何内容,因为文本位于计算机内存中而不是磁盘上。
说实话,我将尽可能少地放在with
块中,以避免出现此类问题。所以我会这样写:
home = os.getcwd()
os.chdir(r'\\CREOL-FAST-01\data')
proj = r'C:\dazzler\data\wavefile.txt'
with open('request.txt', 'w') as file:
file.write(proj)
time.sleep(0.05)
os.chdir(home)
还请记住,您也不能做相反的事情:假设在关闭之前不会写入任何文本。对于像这样的小文件,可能会发生。但是何时将文件写入磁盘取决于很多因素。关闭文件后,它会被写入,但也可能在此之前被写入。