Using subprocess to execute complex command with many arguments - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Using subprocess to execute complex command with many arguments (/thread-39872.html) |
Using subprocess to execute complex command with many arguments - medatib531 - Apr-26-2023 I have a shell script that is as follows: LOAD_RRD=sysmon.rrd DISK_RRD=disk.rrd DISKTEMP_RRD=disktemp.rrd rrdtool graph load1h.png \ -Y -u 1.1 -l 0 -L 5 -v "Load" -w 700 -h 200 -t "Load stats - `/bin/date`" \ --start end-"1h" --x-grid MINUTE:1:MINUTE:5:MINUTE:10:0:%R \ -c ARROW\#000000 \ DEF:load1=$LOAD_RRD:load1:AVERAGE \ DEF:load5=$LOAD_RRD:load5:AVERAGE \ DEF:load15=$LOAD_RRD:load15:AVERAGE \ LINE1:load1\#ff0000:"Load average 1 min" \ LINE1:load5\#ff6600:"Load average 5 min" \ LINE2:load15\#ffaa00:"Load average 15 min" \ COMMENT:" \j" \ COMMENT:"\j" \ COMMENT:" " \ GPRINT:load15:MIN:"Load 15 min minimum\: %lf" \ GPRINT:load15:MAX:"Load 15 min maximum\: %lf" \ GPRINT:load15:AVERAGE:"Load 15 min average\: %lf" \ COMMENT:" \j" \ COMMENT:" " \ COMMENT:" \j" >/dev/null;I want to convert it to python using the subprocess module and run similar commands but with manipulating the internal variables and parameters. I was thinking of copying the whole command in a single python string cmd_str then run subprocess.run(cmd_str, shell=True)But I'm not on the best way to escape all those internal quotes and other special symbols. Any suggestions? RE: Using subprocess to execute complex command with many arguments - Gribouillis - Apr-26-2023 (Apr-26-2023, 01:47 PM)medatib531 Wrote: Any suggestions?Yes you just pass a list of the command's arguments as strings subprocess.run([ "rrdtool", "graph", "load1h.png", "-Y", "-u", "1.1", "-l", "0", "-L", "5", "-v", "Load", ...])Also I see that there is a Python API to rrdtool. Why not use that? RE: Using subprocess to execute complex command with many arguments - medatib531 - Apr-26-2023 But what is the correct way to escape the quotes that are originally in the shell command? E.g. for "Load" should it be something like: subprocess.run([ "rrdtool", "graph", "load1h.png", "-Y", "-u", "1.1", "-l", "0", "-L", "5", "-v", '"Load"', ...])? Also do I have to somehow escape the backslashes, dollar and percent symbols as well, or are they fine within double quotes in the list of strings? RE: Using subprocess to execute complex command with many arguments - DeaD_EyE - Apr-26-2023 https://docs.python.org/3/library/shlex.html#shlex.split import shlex my_command = """ rrdtool graph load1h.png \ -Y -u 1.1 -l 0 -L 5 -v "Load" -w 700 -h 200 -t "Load stats - `/bin/date`" \ --start end-"1h" --x-grid MINUTE:1:MINUTE:5:MINUTE:10:0:%R \ -c ARROW\#000000 \ DEF:load1=$LOAD_RRD:load1:AVERAGE \ DEF:load5=$LOAD_RRD:load5:AVERAGE \ DEF:load15=$LOAD_RRD:load15:AVERAGE \ LINE1:load1\#ff0000:"Load average 1 min" \ LINE1:load5\#ff6600:"Load average 5 min" \ LINE2:load15\#ffaa00:"Load average 15 min" \ COMMENT:" \j" \ COMMENT:"\j" \ COMMENT:" " \ GPRINT:load15:MIN:"Load 15 min minimum\: %lf" \ GPRINT:load15:MAX:"Load 15 min maximum\: %lf" \ GPRINT:load15:AVERAGE:"Load 15 min average\: %lf" \ COMMENT:" \j" \ COMMENT:" " \ COMMENT:" \j" >/dev/null; """.strip().replace("\\", "") my_cmd = shlex.split(my_command) print(my_cmd)The last field ">/dev/null" is wrong, but I guess you still want to suppress stdout: subprocess.run(my_cmd, stdout=subprocess.DEVNULL)Just get rid of the >/dev/null
RE: Using subprocess to execute complex command with many arguments - Gribouillis - Apr-26-2023 (Apr-26-2023, 02:27 PM)medatib531 Wrote: But what is the correct way to escape the quotes that are originally in the shell command?I ran a command to show the arguments received by your program and I get this list, that you can pass to the subprocess.run command (the first argument is missing, it should be the program, 'rrdtool') [ 'graph', 'load1h.png', '-Y', '-u', '1.1', '-l', '0', '-L', '5', '-v', 'Load', '-w', '700', '-h', '200', '-t', 'Load stats - mer. 26 avril 2023 17:11:35 CEST', '--start', 'end-1h', '--x-grid', 'MINUTE:1:MINUTE:5:MINUTE:10:0:%R', '-c', 'ARROW#000000', 'DEF:load1=sysmon.rrd:load1:AVERAGE', 'DEF:load5=sysmon.rrd:load5:AVERAGE', 'DEF:load15=sysmon.rrd:load15:AVERAGE', 'LINE1:load1#ff0000:Load average 1 min', 'LINE1:load5#ff6600:Load average 5 min', 'LINE2:load15#ffaa00:Load average 15 min', 'COMMENT: \\j', 'COMMENT:\\j', 'COMMENT: ', 'GPRINT:load15:MIN:Load 15 min minimum\\: %lf', 'GPRINT:load15:MAX:Load 15 min maximum\\: %lf', 'GPRINT:load15:AVERAGE:Load 15 min average\\: %lf', 'COMMENT: \\j', 'COMMENT: ', 'COMMENT: \\j']@DeaD_EyE 's method using the shlex module is not perfect because it doesn't take into account the string interpolation of the shell, for example the variables $LOAD_RRD, etc By the way, here is my executable "echoargs" script to show arguments #!/usr/bin/env python3 # echoargs script import sys if __name__ == '__main__': print(sys.argv)If you run your shell script by removing > /dev/null and you replace rrdtool with echoargs , it will print the arguments to the console in the same way that they are received by the invoked command after the shell actually processed them.Note that the shell ran /bin/date and replaced it in the result by today's date (in french because it is my locals). So you may need to work a little bit on this, but Python's datetime module should be invoked instead of the /bin/date command to get a more pythonic script.
RE: Using subprocess to execute complex command with many arguments - medatib531 - Apr-27-2023 Worked, thank you all! |