[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

uses both shell and python codes in one script.

On Thu, Oct 3, 2019 at 11:41 PM Hongyi Zhao <hongyi.zhao at gmail.com> wrote:
> On Thu, 03 Oct 2019 23:12:45 +1000, Chris Angelico wrote:
> > Seems fine. Most of the code is elsewhere, and presumably has been
> > written to support both Py2 and Py3; the file you're linking to is
> > *just* a wrapper that finds an interpreter to use.
> >
> > Though this should be unnecessary. A simple shebang of "/usr/bin/env
> > python3" will suffice for many many situations (and then if someone
> > specifically wants to run it in a legacy interpreter, an explicit
> > "python2 scriptname.py" or "python scriptname.py" will work).
> I'm very confusing on the following part in this script:
> ----
> ''':' # begin python string; this line is interpreted by the shell as `:`
> which python  >/dev/null 2>&1 && exec python  "$0" "$@"
> which python3 >/dev/null 2>&1 && exec python3 "$0" "$@"
> which python2 >/dev/null 2>&1 && exec python2 "$0" "$@"
> >&2 echo "error: cannot find python"
> exit 1
> '''
> ----
> Any hints for the meaning of several ' used above?

The hint is there in that line, and stems from the way two different
parsers (Python and sh) interpret the line. In Python, three single
quote characters start a triple-quoted string, which doesn't end till
you get three more; since nothing is done with this string, Python
parses it and then ignores it. In the shell, the first two are an
empty string, then ':' is a colon, which introduces a label (the fact
that it's in quotes is irrelevant to the shell). So there's an empty
label followed by a shell comment. The shell parses this line and does
nothing with it. Then it moves on to the next lines, and runs the
shell script. Since this shell script ends with 'exit 1', it's
guaranteed to halt execution (and usually it'll exec to python, which
also halts execution), so the Python code won't be executed.

This is a common trick when writing polyglot code. You make the
relevant code for one language appear as a comment or string literal
in another. For instance, you can open a C program with "#if 0", which
will cause the following text to be ignored by the C preprocessor; but
since that line begins with a hash, Python will ignore it (but
continue executing).