Python与GnuCash:从GnuCash文件提取数据

6 投票
6 回答
7081 浏览
提问于 2025-04-16 02:07

我想了解如何用Python读取GnuCash文件。我看到有一个叫做 python-gnucash 的东西,它可以让Python和GnuCash库连接起来,但现在用起来挺麻烦的(比如需要处理依赖关系、头文件等等)。而且这些说明主要是针对Linux环境的,而且是个比较旧的GnuCash版本(2.0.x)。我现在用的是GnuCash 2.2.9。虽然我会用Linux命令行,但我是在Windows XP上运行GnuCash。

我主要的目标是读取我的GnuCash文件(暂时没有写入的计划),这样我就可以用 matplotlibwxpython 创建自己的动态可视化报告。我现在还不想学习Scheme语言。

我希望有人能给我一个好的入门建议。根据我对GnuCash和Python的了解,我觉得可能有人知道以下几种解决方案:

  1. 除了 GnuCash wiki上的这份文档,有没有更新的文档?
  2. 有没有什么变通的方法,比如导出成某种文件格式,这种格式有更成熟的Python库可以读取。

你们可能还有更好的建议,除了上面提到的那些。

6 个回答

6

GNUCash 2.4版本发布了。

现在可以导出到SQL格式,这样比解析XML简单多了。

它支持Sqlite、MySQL和PostgreSQL数据库(这真是太酷了!)

8

我发布了一个叫做 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"]])
4

你是在说数据文件吗?从这个维基页面来看,它们其实就是压缩过的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'

撰写回答