Python3 запускает сложную команду оболочки с несколькими предполагаемыми цитатами - PullRequest
0 голосов
/ 05 сентября 2018

Когда я бегу из Баш:

# su -c "psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"" postgres

Работает нормально, но когда я пытаюсь из python:

subprocess.run("su -c \"psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"\" postgres")

Не получается, я пробовал разные кавычки и все не получилось. Не могли бы вы помочь?

1 Ответ

0 голосов
/ 06 сентября 2018

Есть два решения, в зависимости от того, используете ли вы оболочку из Python. Тривиальное, но неэффективное решение - передать строку с shell=True и просто добавить кавычки Python вокруг нее.

subprocess.run(r'''su -c "psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"" postgres''', shell=True,
    # For good measure, you should check its status
    check=True)

Более эффективно и, возможно, фактически более читабельно, вы можете удалить оболочку из уравнения и разбить команду на строки самостоятельно.

subprocess.run([
        'su', '-c',
        # The argument to "su -c" should be one string
        # Because we escaped the shell, the double quotes don't need escaping
        '''psql -d mapping -c "INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');"''',
        'postgres'],
    check=True)

Обратите внимание, что при shell=True первый аргумент является строкой, которая передается в оболочку, тогда как без нее вы передаете список токенов непосредственно на уровень ОС exec() или (несколько менее просто в Windows) CreateProcess(). Обратите также внимание на то, как в первом случае я использовал строку r'...', чтобы избежать влияния Python на обратную косую черту в строке.

...