Python3 run a complex shell command with multiple intended quotations
Python3 run a complex shell command with multiple intended quotations
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?
still the same issue with: subprocess.call("su -c "psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"" postgres")
– user2913139
Sep 5 '18 at 20:01
Instead of calling subprocess.run, use a "print(...)" statement to print out what is getting output. Also, you say it fails -- what error message is being displayed?
– mrunion
Sep 5 '18 at 20:03
if i run print() i got he following error: python3 search.py File "search.py", line 49 print('su -c "psql -d mapping -c \"INSERT INTO mapping (ip,username) VALUES('1.2.3.4','test');\"" postgres") ^ SyntaxError: invalid syntax
– user2913139
Sep 5 '18 at 20:06
when run from subprocess.call i got error: FileNotFoundError: [Errno 2] No such file or directory:...............
– user2913139
Sep 5 '18 at 20:07
1 Answer
1
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.
shell=True
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.
shell=True
exec()
CreateProcess()
r'...'
For more on this, perhaps see also my answer at stackoverflow.com/questions/4256107/…
– tripleee
Sep 6 '18 at 5:32
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You are needing to pass the internal slashes to bash, so try \"INSERT......\"" postgres..... Notice the backslash-backslash -- the first one escapes the second, the third one escapes the double quote inside the double-quoted command in bash.
– mrunion
Sep 5 '18 at 19:27