Reputation: 7745
Quote of the script:
!/bin/sh
## repo default configuration
##
REPO_URL='https://android.googlesource.com/tools/repo'
REPO_REV='stable'
...
magic='--calling-python-from-/bin/sh--'
"""exec" python -E "$0" "$@" """#$magic"
if __name__ == '__main__':
import sys
if sys.argv[-1] == '#%s' % magic:
del sys.argv[-1]
del magic
..all python from here on..
How can they put bash and python in a single script and make it run?
Upvotes: 2
Views: 358
Reputation: 4685
This is how I understand it:
The script is first invoked as a shell script and then calls python on line 23, so if you invoked the sync
command on repo it would do the following:
"""exec" python -E "$0" "$@" """#$magic"
which I believe turns into:
exec "python -E "repo" "sync" "#--calling-python-from-/bin/sh--"
This then calls the script repo
as a python script. You will notice that all of the syntax is legal in bash and python down to the exec
line. The triple quotes on line 23 are really sweet, they work in the shell script and then work as a doc string in python. How awesome is that!
In python """
begin and end a docstring which can span multiple lines. Very roughly, it's a very special kind of comment that the python help system can read. In bash, I believe that the double quote is matched to the next double quote the interpreter encounters. So the first two quotes, quote the null string and it disappears from the interpreter. In our example, the next quotes quote the exec
keyword. The last set of triple quotes, """#$magic"
, first quote the null string and then quote the #$magic
argument. Since double quotes allow the variable $magic
to be expanded, it becomes, #--calling-python-from-/bin/sh--
and passed as an argument.
If you look at the script with a text editor with syntax highlighting as a shell script and then as a python script, it's even easier to see. This is an extremely clever, way of starting the shell script and then giving control to python. Hope this helps!
Upvotes: 3