When i run from bash:
# su -c "psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"" postgres
It works fine, but when i try from python:
subprocess.run("su -c \"psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"\" postgres")
It fails, i have tried different quotation marks and all failing. Could you please help?
There are two solutions, depending on whether or not you use the shell from Python. The trivial but inefficient solution is to pass the string with shell=True
and basically just add Python quoting around it.
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)
More efficiently and perhaps in fact more readably, you can remove the shell from the equation, and split the command into strings yourself.
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)
Notice how with shell=True
the first argument is a string which gets passed to the shell, whereas without it, you pass a list of tokens directly to the OS-level exec()
or (somewhat less straightforwardly on Windows) CreateProcess()
. Notice also how in the first instance I used an r'...'
string to avoid having Python meddle with the backslashes in the string.