[GNC] unable to iterate accounts with API Python bindings
John Ralls
jralls at ceridwen.us
Sat Oct 26 19:59:48 EDT 2024
Jon,
Thanks for digging into it. Reporting that Noah's script works for you in GnuCash 5.5 was very helpful because there's been only one change to the bindings since then: I removed a load call from the Session constructor to fix bug 799308. That wasn't exactly the right thing to do, but it's a surmountable problem: Load the session in the script.
Noah's other problem, that the lock file is left, is because `session` never goes out of scope before the script ends, preventing the destructor from being called. Use Python's RAII keyword `with…;` to ensure that `session` is destroyed. There's one other problem, ACCT_TYPE_STOCK isn't explicitly imported so it needs its package prefix. The following diff fixes all three problems:
--- test.py~ 2024-10-26 16:15:09.000000000 -0700
+++ test.py 2024-10-26 16:30:06.000000000 -0700
@@ -2,14 +2,15 @@
from gnucash import (Session, Account, Transaction, Split, GncNumeric,
SessionOpenMode, gnucash_core)
uri="file:///Users/me/Downloads/gnucash_localSave.gnucash"
-session = Session(book_uri=uri,
-mode=gnucash_core.SessionOpenMode.SESSION_NORMAL_OPEN )
-book = session.book
-table = book.get_table()
-currency_code = 'USD'
-currency = table.lookup('ISO4217', currency_code)
-root_account = book.get_root_account()
-for acc in root_account.get_descendants():
- print('checking a descendant...')
- if acc.GetType() == ACCT_TYPE_STOCK:
- print('found a stock')
+with Session(book_uri=uri,
+ mode=gnucash_core.SessionOpenMode.SESSION_NORMAL_OPEN) as session:
+ session.load()
+ book = session.book
+ table = book.get_table()
+ currency_code = 'USD'
+ currency = table.lookup('ISO4217', currency_code)
+ root_account = book.get_root_account()
+ for acc in root_account.get_descendants():
+ print('checking a descendant...')
+ if acc.GetType() == gnucash_core.ACCT_TYPE_STOCK:
+ print('found a stock')
Note that I didn't change get_descendants() to get_children(). get_children() returns only the immediate children of the account, get_descendants() recursively calls get_children() to return all of the account's descendants. Since Noah is looking for a Stock account and it's rare that a stock account would be at the top level, get_descendants() is the right function.
Now to revisit getting the Session constructor to load xml files since I obviously got that wrong.
Regards,
John Ralls
> On Oct 26, 2024, at 10:21 AM, Jon Schewe <jpschewe at mtu.net> wrote:
>
> Noah and I traded a couple of messages directly about this off-list. I
> tried reading Noah's file and and it worked just fine, get_children
> showed the accounts; on their computer it did not. I was using the
> python bindings for GNuCash 5.5 that are shipped with Ubuntu 24.04. I
> don't know how to get the version of the gnucash bindings from inside
> python, so I'm not sure what version Noah was using, however they are
> on mac OS.
> Does anyone have suggestions why I would see the list of accounts and
> Noah would not?
>
> Example output from my system. Noah gets an empty list when calling
> get_children().
>
>> python3
> Python 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>>>> import gnucash
>>>> filename = 'gnucash_localSave.gnucash'
>>>> session = gnucash.Session(filename,
> gnucash.SessionOpenMode.SESSION_NORMAL_OPEN)
>>>> root_account = session.book.get_root_account()
>>>> root_account.get_children()
> [<gnucash.gnucash_core.Account object at 0x70e7709b6330>,
> <gnucash.gnucash_core.Account object at 0x70e7709b7d10>,
> <gnucash.gnucash_core.Account object at 0x70e7709b7e90>]
>>>> session.end()
>>>> quit()
>
> Jon
>
> On Fri, 2024-10-25 at 19:59 -0500, Jon Schewe wrote:
>> You want "get_children" instead of "get_descendents".
>>
>> On Thu, 2024-10-24 at 21:51 -0700, Noerr via gnucash-user wrote:
>>> Hi,
>>>
>>> I've been trying to get started with the GnuCash API Python
>>> bindings
>>> after just using the main desktop app for the last 12 years.
>>> I built GnuCash app (Build ID: 5.9+(2024-09-28) along with API and
>>> Python
>>> bindings enabled for my system (MacOS 15.0 , M1 Arm)
>>>
>>> My problem is that I haven't been able to interact with my GnuCash
>>> data in
>>> a useful way yet. Namely, I can't seem to access any existing
>>> accounts,
>>> and thus no transactions either. Nor any entries in the price
>>> database.
>>>
>>> First I used the desktop app to save-as a copy of my GnuCash data
>>> in
>>> the
>>> XML format.
>>> Next I use python and commands generally like the following. I do
>>> not see
>>> any output that is expected when iterating over the descendants of
>>> root_account. ( I never see the text output, 'checking a
>>> descendant...' )
>>>
>>>
>>> from gnucash import (Session, Account, Transaction, Split,
>>> GncNumeric,
>>> SessionOpenMode, gnucash_core)
>>> uri="file:///Users/me/Downloads/gnucash_localSave.gnucash"
>>> session = Session(book_uri=uri,
>>> mode=gnucash_core.SessionOpenMode.SESSION_NORMAL_OPEN )
>>> book = session.book
>>> table = book.get_table()
>>> currency_code = 'USD'
>>> currency = table.lookup('ISO4217', currency_code)
>>> root_account = book.get_root_account()
>>> for acc in root_account.get_descendants():
>>> print('checking a descendant...')
>>> if acc.GetType() == ACCT_TYPE_STOCK:
>>> print('found a stock')
>>>
>>>
>>> **So why is root_account.get_descendants() returning an empty
>>> container?**
>>>
>>> The Bindings/API aren't completely dead though. With the same
>>> session and
>>> book open above, I was playing around with some of the ideas
>>> Eberhard
>>> demonstrated in this thread [
>>> https://lists.gnucash.org/pipermail/gnucash-user/2024-September/113402.html
>>> ]
>>> and I called
>>>>>> create_accounts(session, book, root_acct)
>>>>>> quit()
>>>
>>> To my suprise, when I used the desktop app to open
>>> gnucash_localSave.gnucash, my real accounts and transactions are
>>> gone, but
>>> I have three accounts: Expenses, Opening Balance, and Savings in
>>> CAD
>>> currency, and with the specified opening balances.
>>> So the Bindings and API worked to create stuff.
>>>
>>> As an aside, the file did flag as locked upon open in the desktop
>>> app. I
>>> suspect there's a missing unlock somewhere in Python Bindings /
>>> destructor
>>> code.
>>>
>>> Cheers,
>>>
>>> Noah
>>> _______________________________________________
>>> gnucash-user mailing list
>>> gnucash-user at gnucash.org
>>> To update your subscription preferences or to unsubscribe:
>>> https://lists.gnucash.org/mailman/listinfo/gnucash-user
>>> -----
>>> Please remember to CC this list on all your replies.
>>> You can do this by using Reply-To-List or Reply-All.
>>
>> _______________________________________________
>> gnucash-user mailing list
>> gnucash-user at gnucash.org
>> To update your subscription preferences or to unsubscribe:
>> https://lists.gnucash.org/mailman/listinfo/gnucash-user
>> -----
>> Please remember to CC this list on all your replies.
>> You can do this by using Reply-To-List or Reply-All.
>
> _______________________________________________
> gnucash-user mailing list
> gnucash-user at gnucash.org
> To update your subscription preferences or to unsubscribe:
> https://lists.gnucash.org/mailman/listinfo/gnucash-user
> -----
> Please remember to CC this list on all your replies.
> You can do this by using Reply-To-List or Reply-All.
More information about the gnucash-user
mailing list