Python:当文件应该与文本一起保存时,文件被保存为空,但只有在之前运行了一个不相关的方法时
请遵守以下Python文件:Python:当文件应该与文本一起保存时,文件被保存为空,但只有在之前运行了一个不相关的方法时,python,Python,请遵守以下Python文件: # configmanager.py """ ConfigManager controls the modification and validation of config files. """ import os from ruamel import yaml from voluptuous import Schema class ConfigManager(): """ Controls all interaction with con
# configmanager.py
"""
ConfigManager controls the modification and validation of config files.
"""
import os
from ruamel import yaml
from voluptuous import Schema
class ConfigManager():
"""
Controls all interaction with configuration files
"""
def __init__(self):
super().__init__()
self.configvalidator = ConfigValidator()
# The config directory inside users home directory.
# Config files will be stored here.
config_dir = os.path.expanduser('~')+'/.config/MyProject/'
# The default config file
config_file = config_dir+'myproject.conf'
# The default configuration
default_config = {
'key1': {},
'key2': {}
}
def _get_config(self):
"""
Get the config file and return it as python dictionary.
Will create the config directory and default config file if they
do not exist.
"""
# Create config directory if it does not exist
if not os.path.exists(self.config_dir):
os.makedirs(self.config_dir)
# Create default config file if it does not exist
if not os.path.isfile(self.config_file):
config_file = open(self.config_file, 'w')
config_file.write(yaml.dump(self.default_config))
# Open config file, and load from YAML
config_file = open(self.config_file, 'r')
config = yaml.safe_load(config_file)
# Validate config
self.configvalidator.validate(config)
return config
def _save_config(self, config):
"""
Save the config file to disk as YAML
"""
# Open current config file
config_file = open(self.config_file, 'w')
# Validate new config
# THE ERROR IS HERE
# If this runs then the config file gets saved as an empty file.
self.configvalidator.validate(config)
# This shows that the 'config' variable still holds the data
print(config)
# This shows that yaml.dump() is working correctly
print(yaml.dump(config))
config_file.write(yaml.dump(config))
def edit_config(self):
"""
Edits the configuration file
"""
config = self._get_config()
# Perform manipulation on config here
# No actual changes to the config are necessary for the bug to occur
self._save_config(config)
class ConfigValidator():
def __init__(self):
super().__init__()
# Config file schema
# Used for validating the config file with voluptuous
self.schema = Schema({
'key1': {},
'key2': {},
})
def validate(self, config):
"""
Validates the data against the defined schema.
"""
self.schema(config)
app = ConfigManager()
app.edit_config()
-
我的模块说明
这是我正在使用的一个模块,用于修改项目的配置文件。它访问~/.config/MyProject/MyProject.conf
中以YAML格式保存的文件,并存储程序使用的各种信息。我已经删除了尽可能多的代码,只留下理解bug所必需的代码
配置管理器
ConfigManager
是包含用于操作配置文件的方法的类。这里它包含三种方法:\u get\u config()
,\u save\u config()
,和edit\u config()
。实例化后,它将获得ConfigValidator
(如下所述)的实例,并将其分配给self.ConfigValidator
_获取配置
\u get\u config()
只需打开由类变量定义的文件,特别是~/.config/MyProject/MyProject.conf
,或者使用默认值创建文件(如果该文件不存在)。该文件以YAML格式保存,因此该方法使用将其加载到python对象中,使用self.configvalidator.validate(config)
对其进行验证,并返回该文件供其他代码段使用
_保存配置
\u save\u config()
是发生错误的地方,下面将详细介绍。它的目的是验证给定的数据,如果数据有效,则以YAML格式保存到磁盘
编辑配置
这是一个通用函数,在我的程序中,它将根据给定的参数对配置文件进行特定更改。在我的示例中,此函数仅使用self.\u get\u config()
获取配置文件,然后使用self.\u save\u config
保存它,而不做任何更改
配置验证器
此类用于使用验证我的配置文件。实例化后,它将创建要使用的模式,并将其分配给self.schema
。当运行validate
方法时,它使用volupturous
验证给定数据
错误
观察ConfigManager.\u save\u config()
中的行self.configvalidator.validate(config)
。这将根据模式验证给定数据,如果未通过验证,则会引发错误
但是,在下面的config\u file.write(yaml.dump(config))
行中,它只是将给定数据保存到一个文件中作为yaml,它将把一个空的文件保存到磁盘。(注意:文件为空,未删除)
如果我通过注释掉self.configvalidator.validate(config)禁用验证,则文件正确写入为YAML
如果运行了self.configvalidator.validate(config)
,则配置文件保存为空文件
我的测试
从行print(config)
中可以看出,变量config
中的数据在用于验证后不会更改,但在保存到磁盘时,似乎config
是一个空变量
print(yaml.dump(config))
显示ruamel.yaml
工作正常
如果我更改edit_-config
以将无效数据提供给\u-save_-config
,则self.configvalidator.validate(config)
将按预期引发错误<代码>self.configvalidator.validate(config)正在正确运行
终点
如果运行了self.configvalidator.validate(config)
,则config\u file.write(yaml.dump(config))
将配置文件保存为空文件,尽管变量config
中的数据没有更改
如果self.configvalidator.validate(config)
未运行,则config\u file.write(yaml.dump(config))
正确保存文件
这是我的错误,对我来说毫无意义
如果您希望提供帮助,那么只要您的计算机能够访问ruamel.yaml
和voluputous
,那么configmanager.py
应该在您的计算机上正确运行(有错误)。它将创建~/.config/MyProject/MyProject.conf
,然后将其另存为空。保存我的示例myproject.conf
,查看如何在运行configmanager.py
时将其保存为空。如果再次运行configmanager.py
,当myproject.conf
为空时,将在\u get\u config
中引发验证错误,这与预期一致
我被这个错误弄糊涂了,所以如果你有任何见解,我将不胜感激
干杯我不想详细讨论这个问题,但至少有一种情况,可能不止一种情况下,您打开一个文件进行写入,写入,不要关闭它(甚至让它超出范围),然后再次打开它进行读取,这意味着您可能正在读取不完整(未刷新)的文件数据。始终使用
with
语句,尤其是当打开文件进行写入时,因此在with
块的末尾,您处于一种已知的、可预测的状态(写入的任何数据在磁盘上都是明确可见的)。使用实现with
可以解决问题,谢谢。不知道它为什么起作用,但不管怎样\_(ツ)_/''只是添加到@ShadowRanger解释:文件输入/输出操作在计算上非常昂贵。这意味着与其他操作相比,访问和写入磁盘上的文件需要相对较长的时间。在打开和写入文件时,python会缓冲您的输出,并在积累较大数据块时写入文件为节省昂贵的操作而打开。当您对文件对象调用close时,缓冲区将清空,无论它存储了多少数据。请在内容(完成)之前重新打开文件
# ~/.config/MyProject/myproject.conf
key1: {}
key2: {}