Ik kwam een soortgelijk probleem tegen en na een paar uur bloed, zweet en tranen ontdekte ik dat het antwoord slechts de toevoeging van één parameter vereist.
In plaats van
cursor = conn.cursor()
schrijf
cursor = conn.cursor(name="my_cursor_name")
of nog eenvoudiger
cursor = conn.cursor("my_cursor_name")
De details zijn te vinden op http://initd.org/psycopg/docs/usage.html#server-side-cursors
Ik vond de instructies een beetje verwarrend omdat ik dacht dat ik mijn SQL zou moeten herschrijven om "DECLARE my_cursor_name ..." en vervolgens een "FETCH count 2000 FROM my_cursor_name" op te nemen, maar het blijkt dat psycopg dat allemaal voor je doet onder de kap als u gewoon de standaardparameter "name=None" overschrijft bij het maken van een cursor.
De suggestie hierboven om fetchone of fetchmany te gebruiken lost het probleem niet op, want als je de parameter name niet instelt, zal psycopg standaard proberen om de hele query in ram te laden. Het enige andere dat u mogelijk moet doen (naast het declareren van een naamparameter) is het cursor.itersize-attribuut te wijzigen van de standaard 2000 naar 1000 als u nog steeds te weinig geheugen heeft.