Как вызвать и передать несколько команд postgres из python - PullRequest
0 голосов
/ 18 июня 2019

Чтобы скопировать файлоподобный объект в базу данных 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. На данный момент я задаюсь вопросом, возможно ли вообще добиться того, чего я хочу, с помощью вызова подпроцесса.

...