我有一个脚本,可以将YAML文件加载为对象。相关部分非常简单:
def run_test_spec(self, file_path):
try:
with open(file_path, 'r') as f:
test_spec = yaml.load(f)
if test_spec:
do_test(test_spec)
else:
print("empty test_spec")
except BaseException as err:
print("error in loading yaml file:", file_path)
在使用for entries in os.scandir(some_directory)
(在break
循环中没有for
语句)对文件条目进行一些比较之后,传入了 file_path 。>
直到最近它一直运行良好。 test_spec
在第一次运行后获得值None
。我用Pycharm调试了它。如果将断点设置在行if test_spec:
上,则test_spec
是None,但是如果将断点设置在行with open(...)
或yaml.load()
上,则会加载test_spec
正确地。最后,我在time.sleep(0.2)
之前添加了with open(...)
语句,然后它始终有效。
可能的原因是什么?是with open(...)
还是yaml.load()
的问题?不睡觉怎么办?
于2018年6月27日编辑,
我做了进一步的调试,并在代码中找到了区别所在的行。在我计算机上的文件/usr/local/lib/python3.5/dist-packages/yaml/reader.py
中:
def update_raw(self, size=4096):
data = self.stream.read(size)
if self.raw_buffer is None:
self.raw_buffer = data
else:
self.raw_buffer += data
self.stream_pointer += len(data)
if not data:
self.eof = True
如果将断点设置为第一行(data = ...
),则将data
与文件内容一起很好地读取,但是,将断点设置为第二行({{1 }}),将if self.raw_buffer is None:
作为一个空字符串读入,这导致了data
,并因此从StreamEndEvent
中返回了空值。
我无法进入yaml.load()
,只能进入self.stream.read(size)
中的某些代码。
我不认为是Python库导致了此问题。可能与我的代码有关。我注意到在运行测试后会发生这种情况,其中涉及产生两个作为管道运行的子进程,并使用/usr/lib/python3.5/codecs.py
杀死第二个进程。我用terminate()
检查了程序,运行后只有一个线程,没有子进程,没有打开文件。看起来很干净。但是然后无法读取新的请求文件,除非我在读取流之前添加了睡眠或稍作休息。如果同样在管道中的第二个进程本身终止,则不会发生此问题。
如果未设置断点,而只是在调用psutil
之前打印f.tell()
,则无论yaml.load(f)
是否返回None,它始终为0。
答案 0 :(得分:0)
PyYAML昨天(2018-06-26)收到new release。没有宣布这表明API中断的公告,但是可以预料到主要版本号的更改。
您使用的(不安全的)load()
已重命名
danger_load()
通过合并this PR
您可以将PyYAML安装固定在3.x(pip install "pyyaml<4"
)上,或将代码更改为使用danger_load()
。最好的解决方案可能是使用!!python/path_to_your_type
为现在转储的对象编写显式表示符,以便可以使用safe_load()
。
我在文档中找不到任何可能损坏的通知。