#python #json #postgresql #psycopg2
Вопрос:
Я передаю объекты jsonb из таблицы postgres в виде большого application/jsonl
http-ответа. Это действительно хорошо работает:
def stream_json_from_copy_syntax():
conn = psycopg2.connect(...)
cur = conn.cursor()
file = BytesIO()
cur.copy_expert(
sql="COPY (select my_jsonb from large_table) TO STDOUT WITH (FORMAT text)",
file=file
)
file.seek(0)
for line in file.readlines():
line = unescape(line)
yield line
Все вышесказанное помещается в ответную колбу. Это быстро и занимает очень мало места в памяти.
Поле jsonb изначально правильно экранировано, но, похоже (FORMAT text)
, добавляется дополнительное экранирование.
Это превращается My string
в json propper "My \ string"
, а затем в "My \\ string"
. Так что происходит дополнительный побег. На данный момент я справился с этим с помощью:
def unescape(line):
return line.replace(b'\\', b'\')
Я думаю, что это решает большинство проблем, если не все, но я немного не уверен, есть ли другие вещи, с которыми я не справлялся. (FORMAT text)
Как мне правильно развернуть то, что (FORMAT text)
делает? Или есть способ вообще не позволить ему избежать чего-либо, потому что первоначальный побег json работает нормально.
Обратите внимание, что использование (ESCAPE 'escape_character')
применимо только к (FORMAT csv)
: https://www.postgresql.org/docs/current/sql-copy.html
Ответ №1:
Вы экспортируете данные в формате, который копирует Postgres…ОТ бы понял. Возможно, вам нужен другой формат, например CSV.
Комментарии:
1. Знаете ли вы, существует ли библиотека postgres unescape или, может быть, фактическая кодовая база, которую postgres использует для анализа файлов в текстовом формате, в которой я мог бы переопределить в python? Но да. Возможно, если я переконфигурирую версию CSV. Когда я наивно попробовал это сделать, это дало мне кучу дополнительных цитат, но их, возможно, можно удалить.
2. Вы можете использовать psycopg 3 и получить объекты на Python, а затем отформатировать их так, как вы хотите.