2

参考https://github.com/noxrepo/pox/blob/carp/pox.py

我试图理解 4 个撇号是什么意思?它看起来不像是注释,并且在代码末尾附近还有另外 3 个撇号。有人可以帮助解释下面的代码吗?

#!/bin/sh -

''''true
#export OPT="-u -O"
export OPT="-u"
export FLG=""
if [ "$(basename $0)" = "debug-pox.py" ]; then
  export OPT=""
  export FLG="--debug"
fi

if [ -x pypy/bin/pypy ]; then
  exec pypy/bin/pypy $OPT "$0" $FLG "$@"
fi

if type python2.7 > /dev/null 2> /dev/null; then
  exec python2.7 $OPT "$0" $FLG "$@"
fi
exec python $OPT "$0" $FLG "$@"
'''
from pox.boot import boot
if __name__ == '__main__':
  boot()
4

2 回答 2

3

总体答案

前三个撇号开始一个多行字符串。下一个撇号只是字符串内容的一部分。

检查结果

该脚本将字符串存储在__doc__变量中。使用 交互式运行代码后python -i pox.py,很容易直接看到解析后的文档字符串

>>> print __doc__
'true
#export OPT="-u -O"
export OPT="-u"
export FLG=""
if [ "$(basename $0)" = "debug-pox.py" ]; then
  export OPT=""
  export FLG="--debug"
fi

if [ -x pypy/bin/pypy ]; then
  exec pypy/bin/pypy $OPT "$0" $FLG "$@"
fi

if type python2.7 > /dev/null 2> /dev/null; then
  exec python2.7 $OPT "$0" $FLG "$@"
fi
exec python $OPT "$0" $FLG "$@"

请注意第四个撇号是如何作为文档字符串的一部分保留的。

细节

根据tokenize模块,以下是 Python 对上述代码的看法:

NL        : '\n'
COMMENT   : '#!/bin/sh -'
NL        : '\n'
NL        : '\n'
STRING    : '\'\'\'\'true\n#export OPT="-u -O"\nexport OPT="-u"\nexport FLG=""\nif [ "$(basename $0)" = "debug-pox.py" ]; then\n  export OPT=""\n  export FLG="--debug"\nfi\n\nif [ -x pypy/bin/pypy ]; then\n  exec pypy/bin/pypy $OPT "$0" $FLG "$@"\nfi\n\nif type python2.7 > /dev/null 2> /dev/null; then\n  exec python2.7 $OPT "$0" $FLG "$@"\nfi\nexec python $OPT "$0" $FLG "$@"\n\'\'\''
NEWLINE   : '\n'
NAME      : 'from'
NAME      : 'pox'
OP        : '.'
NAME      : 'boot'
NAME      : 'import'
NAME      : 'boot'
NEWLINE   : '\n'
NAME      : 'if'
NAME      : '__name__'
OP        : '=='
STRING    : "'__main__'"
OP        : ':'
NEWLINE   : '\n'
INDENT    : '  '
NAME      : 'boot'
OP        : '('
OP        : ')'
NEWLINE   : '\n'
DEDENT    : ''
ENDMARKER : ''

标记化脚本

这是一个标记pox.py脚本的 Python 2.7脚本:

from __future__ import print_function
import tokenize
import token

with open('pox.py') as f:
    for tok in tokenize.generate_tokens(f.readline):
        tok_type, tok_str, (srow, scol), (erow, ecol), logical_lineno = tok
        print('%-10s: %r' % (token.tok_name[tok_type], tok_str))
于 2017-11-07T04:09:20.193 回答
0

这是一个可以作为 shell 脚本Python 脚本执行的文件。请注意 shebang 是#!/bin/sh,因此该脚本旨在首先作为 shell 脚本运行。(我忽略了这个-参数,这表明sh应该从标准输入而不是文件中读取。我不太确定它在这里的意义是什么,因为我从未见过这样写的 shebang。)

预期的调用类似于./pox.py ...sh ./pox.py ...

脚本的第一行是''''true,在去掉引号之后与 相同true,因此该命令运行并且除了成功退出之外什么都不做。以下几行是确定使用哪个 Python 解释器以及传递给调用的选项的有效命令。三个exec命令之一

  1. exec pypy/bin/pypy $OPT "$0" $FLG "$@"
  2. exec python2.7 $OPT "$0" $FLG "$@"
  3. exec python $OPT "$0" $FLG "$@"

然后将执行与 Python 脚本相同的文件,因此'''shell 永远不会看到以第二个开头的行(这很好,因为第一个开头的单词'既不会以最终的 close 结尾',字符串也不会是有效的命令,如果它终止)。"$0"是当前文件的名称,并"$@"表示脚本的参数(shell 脚本会忽略这些参数,除非传递给 Python 脚本,如此处所示)。

一旦脚本作为 Python 脚本运行,开始的行''''true就被简单地视为将被忽略的 doc 字符串的开头。正确的 Python 脚本很简单

from pox.boot import boot
if __name__ == '__main__':
  boot()

至于为什么这一切都要从头说起''''true?作为一个shell脚本,你需要有偶数个引号来相互平衡。但是,''''shell 将尝试将其视为命令的空字符串,并且没有名称为空字符串的命令。''''true但是,确实会产生有效的命令。

于 2017-11-07T14:19:34.293 回答