You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Beancount 2.3.5代码未生成复式记账文件,如何修改实现生成?

Beancount 2.3.5生成分类账文件及过账交易的解决方案

问题描述

我正在使用Beancount 2.3.5,尝试编写一个概念验证文件,实现以下功能:

  • 创建简单的会计科目表
  • 通过复式记账法将样本交易过账到分类账中

以下是我的代码:

from datetime import datetime
from decimal import Decimal as D

import beancount.core.data as data

line_number = 42
metadata = data.new_metadata(filename='./myfile.beancount', lineno=line_number)

# define accounts
accounts = ["Assets:Bank", "Expenses:Groceries"]

# create postings
posting1 = data.Posting(accounts[0], data.Amount(D('1000'), 'USD'), None, None, None, meta=metadata)
posting2 = data.Posting(accounts[1], data.Amount(D('200'), 'USD'), None, None, None, meta=metadata)

# create transactions
transaction1 = data.Transaction(
    meta = metadata,
    date = datetime.strptime("2022-03-29", '%Y-%m-%d'),
    flag = "*",
    payee = "Bob's Grocery Store",
    narration = "Groceries for the week",
    tags = set(),
    links = set(),
    postings = [posting1, posting2]
)

运行代码后,期望生成新的myfile.beancount文件,其中包含上述交易,但实际并未生成任何文件。怀疑需要先将账户标记为已开户,但找不到合适的操作入口,请问如何修改代码以生成文件并正确将交易过账到文件中?

修改方案

你的代码仅在内存中创建了交易对象,缺少序列化到文本文件的步骤,同时确实需要先添加账户开户指令(Beancount要求所有使用的账户必须先完成开户)。以下是完整的修改代码及说明:

修改后的完整代码

from datetime import datetime
from decimal import Decimal as D

import beancount.core.data as data
import beancount.core.printer as printer

# 初始化元数据
filename = './myfile.beancount'
line_number = 1
metadata = data.new_metadata(filename=filename, lineno=line_number)

# 定义账户列表
accounts = ["Assets:Bank", "Expenses:Groceries"]
account_currency = 'USD'
open_date = datetime.strptime("2022-01-01", '%Y-%m-%d').date()

# 创建账户开户条目
open_entries = []
for account in accounts:
    open_meta = data.new_metadata(filename, line_number)
    open_entry = data.Open(
        meta=open_meta,
        date=open_date,
        account=account,
        currencies={account_currency},
        booking=None
    )
    open_entries.append(open_entry)
    line_number += 1

# 创建交易的posting(注意金额需符合复式记账平衡:总额为0)
# 买 groceries 是银行账户减少200USD,费用增加200USD
posting_meta = data.new_metadata(filename, line_number)
posting1 = data.Posting(
    account=accounts[0],
    amount=data.Amount(D('-200'), 'USD'),
    cost=None,
    price=None,
    flag=None,
    meta=posting_meta
)
line_number += 1

posting_meta2 = data.new_metadata(filename, line_number)
posting2 = data.Posting(
    account=accounts[1],
    amount=data.Amount(D('200'), 'USD'),
    cost=None,
    price=None,
    flag=None,
    meta=posting_meta2
)
line_number += 1

# 创建交易条目
transaction_meta = data.new_metadata(filename, line_number)
transaction1 = data.Transaction(
    meta=transaction_meta,
    date=datetime.strptime("2022-03-29", '%Y-%m-%d').date(),
    flag="*",
    payee="Bob's Grocery Store",
    narration="Groceries for the week",
    tags=set(),
    links=set(),
    postings=[posting1, posting2]
)

# 合并所有条目(开户+交易)
all_entries = open_entries + [transaction1]

# 将条目序列化为Beancount格式文本
beancount_text = printer.print_entries(all_entries)

# 写入文件
with open(filename, 'w', encoding='utf-8') as f:
    f.write(beancount_text)

关键修改说明

  1. 添加账户开户条目:
    使用data.Open创建每个账户的开户记录,指定账户名、支持的币种和开户日期,这是Beancount的必填要求。
  2. 修复交易金额平衡:
    原代码中交易的金额总和不为0(1000+200=1200),不符合复式记账规则。修改为银行账户减少200USD(负金额)、费用账户增加200USD(正金额),确保总额为0。
  3. 序列化与文件写入:
    导入beancount.core.printer模块,使用printer.print_entries()将内存中的条目转换为标准Beancount格式的文本,再通过Python文件操作写入目标文件。
  4. 元数据行号管理:
    逐步递增行号,让生成的文件中每个条目都有正确的元数据行号,便于后续调试。

生成的myfile.beancount内容示例

2022-01-01 open Assets:Bank USD
2022-01-01 open Expenses:Groceries USD

2022-03-29 * "Bob's Grocery Store" "Groceries for the week"
  Assets:Bank                   -200.00 USD
  Expenses:Groceries            200.00 USD

内容的提问来源于stack exchange,提问作者Homunculus Reticulli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:55:08