Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the equivalent to Bash's exec $@ in Python?

Tags:

python

bash

Some bash scripts end their execution with exec "$@", often invoking a series of commands before finally replacing their execution with the arguments passed initially to the script.

If you were to write a Python script to replace that bash script, what would the final command be?

like image 622
coiax Avatar asked Mar 21 '19 16:03

coiax


1 Answers

In bash,

"$@" is an array-like construct of all positional parameters, {$1, $2, $3 ...}.

See https://stackoverflow.com/a/5163260/1420079

So exec "$@" would invoke all of the additional positional parameters, with the first argument being the program name, and then subsequent arguments being the arguments to that replacement program.

In Python, sys.argv (from the sys module) is...

The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.

See https://docs.python.org/3/library/sys.html#sys.argv

Replacing the current running process with another is a job for the os.exec* family of functions (unsurprisingly, from the os module), see https://docs.python.org/3/library/os.html#os.execvp

If Bash's exec is invoked without the -c flag, it inherits the environment of the current process, and also uses the $PATH variable to look up the program to execute if the path isn't absolute.

As such, the closest exec* function is os.execvp (variable number of arguments, using path). Also to bare in mind is...

The various exec* functions take a list of arguments for the new program loaded into the process. In each case, the first of these arguments is passed to the new program as its own name rather than as an argument a user may have typed on a command line. For the C programmer, this is the argv[0] passed to a program’s main(). For example, os.execvp('/bin/echo', ['foo', 'bar']) will only print bar on standard output; foo will seem to be ignored.


So, I would implement Bash's exec "$@" in Python as follows (assuming os and sys are imported):

os.execvp(sys.argv[1], sys.argv[1:])

This isn't a perfect replication, Bash's exec will handle no arguments as a no-op, while this code will throw an IndexError.

like image 81
coiax Avatar answered Oct 12 '22 14:10

coiax