python 如何才能正确处理包含中文的Yaml文件?

tim_spac 2009-03-10 08:25:05
新学使用yaml作为程序配置文件;感觉很好 -- 易读,易写,易解析,易用。
例如:

# Yaml格式配置文件 Config.yaml
host: dbhost
user: dbuser
password: "dbpwd"
database: thetestdb
sqlstring_summaryDaily:
select [date], charge, monthsummary
from ds_collect
where code=$code
order by [date] desc

threshold_values:
"099023":
name: name of the custmoer
daily: 600.00
monthSummary: 2500.00

"000000":
name: 2nd customer's name
daily: 800.00
monthSummary: 3000.00

# 以下为Python脚本代码 #############################

#!python
# -*- coding:GBK -*-

import yaml
import pymssql
import string

config = yaml.load(file('Config.yaml', 'r'))
conn = pymssql.connect(host=config['host'],
user=config['user'],
password=config['password'],
database=config['database'])
conn.row_factory=str
curr = conn.cursor()

pageTmpl = "$name .. <table><tr><td>Date</td><td>Daily</td><td>MnSummary</td></tr>$trs</table>" # 此处具体内容简化

trFmt = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>"

for code in config['threshold_values']:
tvalues = config['threshold_values'][code]
dgate , mgate = float(tvalues['daily']) , float(tvalues['monthSummary'])
trs , atrs = [] , ""

curr.execute(string.Template(config['sqlstring_summaryDaily']).safe_substitute(dict(code=code)))
for (date,dsum, msum,) in curr.fetchall():
trs.append(trFmt % (
date.strftime("%d, %b"),
dsum,
msum))

open("%s.html" % code,"w").writelines(pageTmpl.safe_substitute(dict(
name = tvalues['name'], trs = "\n".join(trs),
)))

curr.close()
conn.close()


>> 可以很方便地生成客户报表,并按需要修改配置文件..
但是如果在配置文件中存在中文(例如 ... name: 客户名称 ...)将遇到报错:
yaml.reader.ReaderError: 'utf8' codec can't decode byte #xb4: unexpected code byte ...
如何解决呢?
...全文
1374 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
InOner 2009-09-26
  • 打赏
  • 举报
回复
HTWL例子
========

名称: HTWL
语言: !选项 中文,英文,繁体中文
...

InOner 2009-09-26
  • 打赏
  • 举报
回复
用HTWL吧,支持中文,中文符号。99%兼容yaml.
lixq2000 2009-03-16
  • 打赏
  • 举报
回复
进来学习!
DDGG 2009-03-12
  • 打赏
  • 举报
回复
说得很有道理,呵呵。
iambic 2009-03-12
  • 打赏
  • 举报
回复
另外一个传输协议选择是源于JavaScript的JSON。非常紧凑,不适合作为配置文件,但是很适合作为数据传输协议。缺点就是太简单了。有时候需要传递递归数据结构就很费劲。
iambic 2009-03-12
  • 打赏
  • 举报
回复
对,XML用的是比较多些,差不多成标准了吧。特别是数据交换的时候。
但是,大多数情况下,其实不需要其他语言其他应用程序进行交互。特别是配置文件的读取,一般就用一段固定的代码搞定。
YAML其实已经很流行了,Perl中的YAML好像历史悠久;Google AppEngine据说也是用的YAML做培植文件。现在找个YAML的某种语言的实现,应该非常容易。
YAML本身就很简单,使用也很简单。相比之下,大多数语言处理XML还是非常费劲,虽然支持很成熟,但是很难用。印象中ActionScript这样内建支持XML的语言还比较方便,其他通过库来支持XML的都很不爽。
DDGG 2009-03-12
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 iambic 的回复:]
XML兼容性好不清楚指的是哪一方面?
[/Quote]

我的意思是,Python和其他语言混合编程的时候,使用XML比较方便,大家都有解析这种文件格式的能力。
tim_spac 2009-03-12
  • 打赏
  • 举报
回复
18:00前结贴。
tim_spac 2009-03-12
  • 打赏
  • 举报
回复
iambic:
Step 1:---------------------------------------------
原代码:
...
open("%s.html" % code,"w").writelines(pageTmpl.safe_substitute(dict(
name = tvalues['name'], trs = "\n".join(trs),
)))
...

替代为
...
handle = open("%s.html" % code,"w")
content = pageTmpl.safe_substitute(dict(name = tvalues['name'], trs = "\n".join(trs), ))
for b in content:
handle.write(b)
handle.close()
...

得到消息:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

Step 2:---------------------------------------------
handle.write(b) 改为 handle.write(b.encode("utf-8")) 成功

Step 3:---------------------------------------------
再改回writelines

open("%s.html" % code,"w").writelines(pageTmpl.safe_substitute(dict(
name = tvalues['name'], trs = "\n".join(trs),
)).encode("utf-8"))

成功。

thanks.
iambic 2009-03-12
  • 打赏
  • 举报
回复
YAML的可读性略好些,把YAML文件和简单数据结构进行转换也非常容易——直接把yaml load进来就是一个python字典或者列表,不用像XML那样折腾element、attribute。

XML兼容性好不清楚指的是哪一方面?
DDGG 2009-03-12
  • 打赏
  • 举报
回复
Yaml是什么?为什么不用XML做配置文件呢?兼容性好。
iambic 2009-03-12
  • 打赏
  • 举报
回复
把writelines换成write试下。
tim_spac 2009-03-11
  • 打赏
  • 举报
回复
首先感谢您的回复。

修改配置文件为utf-8编码格式后,得到如下错误消息。

areaWarning = "" if not atrs else areaWarning.safe_substitute(dict(trs=atrs))
TypeError: writelines() argument must be a sequence of strings

完整的代码如下:

#!python
# -*- coding:utf-8 -*-

import yaml
import pymssql
import string

config = yaml.load(file('testcfg.yaml', 'r'))
conn = pymssql.connect(host=config['host'],
user=config['user'],
password=config['password'],
database=config['database'])
conn.row_factory=str
curr = conn.cursor()

pageTmpl = "$name .. <table><tr><td>Date</td><td>Daily</td><td>MnSummary</td></tr>$trs</table>"

trFmt = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>"

for code in config['threshold_values']:
tvalues = config['threshold_values'][code]
dgate , mgate = float(tvalues['daily']) , float(tvalues['monthSummary'])
trs , atrs = [] , ""

curr.execute(string.Template(config['sqlstring_summaryDaily']).safe_substitute(dict(code=code)))
for (date,dsum, msum,) in curr.fetchall():
trs.append(trFmt % (
date.strftime("%d, %b"),
dsum,
msum))

open("%s.html" % code,"w").writelines(pageTmpl.safe_substitute(dict(
name = tvalues['name'], trs = "\n".join(trs),
)))

curr.close()
conn.close()

配置文件如下:
host: 192.168.10.15
user: sa
password: "780702"
database: gabill
sqlstring_summaryDaily:
select [date], charge, monthsummary
from ds_collect
where code=$code
order by [date] desc

threshold_values:
"099023":
name: 重要客户
daily: 600.00
monthSummary: 2500.00

"000000":
name: 测试客户
daily: 800.00
monthSummary: 3000.00
iambic 2009-03-10
  • 打赏
  • 举报
回复
你的配置文件是gbk编码的,转成utf-8的试试。

37,720

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧