Python与GnuCash:从GnuCash文件提取数据
我想了解如何用Python读取GnuCash文件。我看到有一个叫做 python-gnucash
的东西,它可以让Python和GnuCash库连接起来,但现在用起来挺麻烦的(比如需要处理依赖关系、头文件等等)。而且这些说明主要是针对Linux环境的,而且是个比较旧的GnuCash版本(2.0.x)。我现在用的是GnuCash 2.2.9。虽然我会用Linux命令行,但我是在Windows XP上运行GnuCash。
我主要的目标是读取我的GnuCash文件(暂时没有写入的计划),这样我就可以用 matplotlib
和 wxpython
创建自己的动态可视化报告。我现在还不想学习Scheme语言。
我希望有人能给我一个好的入门建议。根据我对GnuCash和Python的了解,我觉得可能有人知道以下几种解决方案:
- 除了 GnuCash wiki上的这份文档,有没有更新的文档?
- 有没有什么变通的方法,比如导出成某种文件格式,这种格式有更成熟的Python库可以读取。
你们可能还有更好的建议,除了上面提到的那些。
6 个回答
GNUCash 2.4版本发布了。
现在可以导出到SQL格式,这样比解析XML简单多了。
它支持Sqlite、MySQL和PostgreSQL数据库(这真是太酷了!)
我发布了一个叫做 piecash 的工具,它是一个用 Python 编写的接口,可以让你访问保存了 GnuCash 账本的 SQL 数据库,底层使用了 SQLAlchemy 这个库(https://github.com/sdementen/piecash)。
通过这个工具,你可以轻松获取账本中的所有信息。
比如,你可以遍历账本中的所有账户:
from piecash import open_book
# open a book
with open_book("some_book.gnucash", open_if_lock=True) as mybook:
# iterate over all accounts of the book
for account in mybook.accounts:
print(account)
或者你可以遍历“资产”账户中的所有分项:
# open the book
with open_book("some_book.gnucash", open_if_lock=True) as mybook:
# retrieve the account by its fullname
asset = mybook.accounts(fullname="Asset")
# iterate over all its splits
for split in asset.splits:
print(split)
最近的版本还允许你直接将分项信息提取到 pandas 数据框中,这样就可以方便地进行绘图和分析:
from piecash import open_book
# open a book
with open_book("some_book.gnucash", open_if_lock=True) as mybook:
# extract all split information to a pandas DataFrame
df = mybook.splits_df()
# print for account "Asset" some information on the splits
print(df.loc[df["account.fullname"] == "Asset",
["transaction.post_date", "value"]])
你是在说数据文件吗?从这个维基页面来看,它们其实就是压缩过的XML文件。你可以用Python来解压这些文件,方法是使用gzip模块,然后用任何一个可用的XML解析器来解析它们。
ElementTree 示例
>>> import xml.etree.cElementTree as ET
>>> xmlStr = '''<?xml version="1.0" encoding="UTF-8" ?>
<painting>
<img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
<caption>This is Raphael's "Foligno" Madonna, painted in
<date>1511</date>?<date>1512</date>.
</caption>
</painting>
'''
>>> tree = ET.fromstring(xmlStr) #use parse or iterparse to read direct from file path
>>> tree.getchildren()
[<Element 'img' at 0x115efc0>, <Element 'caption' at 0x1173090>]
>>> tree.getchildren()[1].text
'This is Raphael\'s "Foligno" Madonna, painted in\n '
>>> tree.getchildren()[0].get('src')
'madonna.jpg'