如何在Python中从YAML存储或读取换行符和回车符
我今天一直在为这个问题苦恼,网上也找不到答案。我有一个yaml文档,用来存储我的消息/响应服务器的一些配置,其中一个参数是“message_terminator”。你可以猜到,这个参数就是我的服务器用来识别客户端发送的消息结束符。
\r\n
这是telnet默认发送的,所以我就把它设置成这样。
Yaml文档:
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: \r\n
我想做的是把message_terminator的值读取为实际的回车和换行,或者把它从字符串表示转换为二进制转义码:回车和换行,而不是字符串表示的"\r\n"
比如说,如果我在python中这样做:
print('\r\n')
它会打印出一个回车和换行,而不是字符本身。但如果我用以下方式从yaml配置中读取这个值:
print(config['global']['message_terminator'])
它就会打印出字符:
\r\n
修改yaml文档并添加引号,比如:
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: '\r\n'
还有
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: b'\r\n'
甚至
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: !!str \r\n
或者
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: !!python/bytes b'\r\n'
都没有效果。当消息结束符被打印出来时,它打印的是字符。当它通过网络发送给客户端时,也是字符。
我还尝试过一些其他方法:
print(bytes(config['global']['message_terminator'], 'utf-8').encode('unicode_escape'))
但仍然只是打印出字符。
如果我完全搞错了或者漏掉了什么,请多多包涵。我还在搞清楚字符串、字节、原始字符串等之间的区别。欢迎任何建议或指点。谢谢你的时间。
编辑 @Jan:在解释器中这样做是有效的。我得到了一个回车和换行的打印,而不是字符。
>>> text = """
... val: "hello\\n\\rnew line"
... """
>>> text
'\nval: "hello\\n\\rnew line"\n'
>>> print(text)
val: "hello\n\rnew line"
>>> import yaml
>>> data = yaml.load(text)
>>> data
{'val': 'hello\n\rnew line'}
>>> print(data['val'])
hello
new line
>>>
但是在我的主代码中,当我从yaml文件加载时,它打印的是\r\n,而不是实际的回车和换行。这段python代码:
TERM = config['global']['message_terminator']
print(TERM)
print(config['global']['message_terminator'])
print("netcmd server started on port", PORT)
在终端中打印出:
$ python3 netcmd.py
\r\n
\r\n
netcmd server started on port 7040
为了澄清,我想要的是回车和换行的动作,而不是字符表示。
编辑 2:问题解决了。在Jan的更新后,我把yaml文件从:
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: "\\r\\n"
改成了
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: "\r\n"
现在一切都正常工作,python代码从yaml文件中读取并打印出实际的回车和换行。
1 个回答
YAML 允许使用反斜杠(\)来转义字符,但你需要把值放在引号里:
>>> text = """
... val: "hello\\n\\rnew line"
... """
...
>>> text
'\nval: "hello\\n\\rnew line"\n'
>>> data = yaml.load(text)
>>> data
{'val': 'hello\n\rnew line'}
所以你包含 global
的文件可以这样工作:
global:
server_port: 7040
bound_ip: 0.0.0.0
message_terminator: "\r\n"
5.7. 转义字符
所有不可打印的字符都必须进行转义。YAML 的转义序列使用“\”这种符号,这在大多数现代编程语言中都很常见。每个转义序列都必须被解析成相应的 Unicode 字符。原始的转义序列只是一个展示细节,不能用来传达内容信息。
注意,转义序列只在双引号的标量中被解释。在其他所有标量样式中,“\”字符没有特殊含义,无法使用不可打印的字符。