Ich bin auf ein ähnliches Problem gestoßen und nach ein paar Stunden voller Blut, Schweiß und Tränen stellte ich fest, dass die Antwort einfach das Hinzufügen eines Parameters erfordert.
Statt
cursor = conn.cursor()
schreiben
cursor = conn.cursor(name="my_cursor_name")
oder noch einfacher
cursor = conn.cursor("my_cursor_name")
Die Details finden Sie unter http://initd.org/psycopg/docs/usage.html#server-side-cursors
Ich fand die Anweisungen etwas verwirrend, da ich mein SQL umschreiben müsste, um "DECLARE my_cursor_name ..." und dann "FETCH count 2000 FROM my_cursor_name" einzuschließen, aber es stellt sich heraus, dass psycopg das alles für Sie unter tut die Haube, wenn Sie beim Erstellen eines Cursors einfach den Standardparameter "name=None" überschreiben.
Der obige Vorschlag, fetchone oder fetchmany zu verwenden, löst das Problem nicht, da psycopg standardmäßig versucht, die gesamte Abfrage in den Arbeitsspeicher zu laden, wenn Sie den Namensparameter nicht gesetzt lassen. Die einzige andere Sache, die Sie möglicherweise noch tun müssen (neben der Deklaration eines Namensparameters), ist, das Attribut cursor.itersize von der Vorgabe 2000 auf 1000 zu ändern, wenn Sie immer noch zu wenig Speicher haben.