Natknąłem się na podobny problem i po kilku godzinach krwi, potu i łez znalazłem odpowiedź, która wymaga po prostu dodania jednego parametru.
Zamiast
cursor = conn.cursor()
pisać
cursor = conn.cursor(name="my_cursor_name")
lub jeszcze prostsze
cursor = conn.cursor("my_cursor_name")
Szczegóły można znaleźć pod adresem http://initd.org/psycopg/docs/usage.html#server-side-cursors
Uważam, że instrukcje są nieco mylące, ponieważ pomyślałem, że musiałbym przepisać mój kod SQL, aby zawierał „DECLARE my_cursor_name ...”, a następnie „FETCH count 2000 FROM my_cursor_name”, ale okazuje się, że psycopg robi to wszystko za ciebie pod okapu, jeśli po prostu nadpiszesz domyślny parametr „nazwa=Brak” podczas tworzenia kursora.
Powyższa sugestia użycia fetchone lub fetchmany nie rozwiązuje problemu, ponieważ jeśli pozostawisz nieustawiony parametr name, psycopg domyślnie spróbuje załadować całe zapytanie do pamięci RAM. Jedyną inną rzeczą, którą możesz potrzebować (poza zadeklarowaniem parametru nazwy), jest zmiana atrybutu cursor.itersize z domyślnego 2000 na 1000, jeśli nadal masz za mało pamięci.