Чтобы скопировать файлоподобный объект в базу данных postgres , я предпринимаю следующие шаги:
~$ sudo psql -U postgres
password for root:
password for user postgres:
postgres=# \c migration v0
You are now connected to database "migration_v0" as user "postgres".
migration_v0=# cat file.csv | \copy table1 from stdin csv
Я хочу сделать точно такие же шаги, но изнутри Python и хочу передать буфер StringIO
вместо литерального файла. Моя первая попытка состояла из следующих шагов:
# test.py
fmt = r"copy table1 FROM stdin csv"
sql = fmt.format(string_io)
psql = ['psql', '-U', 'postgres', '-c', sql]
output = subprocess.check_output(psql)
print(output)
Команда выполнена (появляется запрос на ввод пароля для пользователя postgres ), но я получаю следующую ошибку:
ОШИБКА: отношение "таблица1" не существует
Это происходит потому, что я сейчас пытаюсь выполнить \copy
в базе данных по умолчанию postgres
вместо migration_v0
. Таким образом, я хочу включить обе команды в вызов подпроцесса (\c migration_v0
и \copy ...
) и не знаю, как это сделать, поскольку флаг postgres -c
принимает только одну команду.
Я нашел обходной путь и наткнулся на пример командной строки:
\c migration_v0 \\ \copy ... | psql -U postgres
, но я понятия не имею, как я могу перенести это на код Python.
Любые предложения о том, как я могу это осуществить?
Редактировать 1
Я понял, что флаг -d
также позволяет переключать базы данных, так что теперь мне не нужно запускать несколько команд. Мой код теперь выглядит так:
p = subprocess.Popen([
'psql', '-U', 'postgres',
'-d', 'migration_v0',
'-c', '\copy table1 FROM stdin csv'],
shell=False,
stdin=string_io)
но я получаю следующую ошибку:
io.UnsupportedOperation: fileno
Очевидно, StringIO
не реализует fileno
. На данный момент я задаюсь вопросом, возможно ли вообще добиться того, чего я хочу, с помощью вызова подпроцесса.