参考 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()
总体答案
前三个撇号开始一个多行字符串。 下一个撇号只是字符串内容的一部分。
检查结果
该脚本将字符串存储在__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 : '''''truen#export OPT="-u -O"nexport OPT="-u"nexport FLG=""nif [ "$(basename $0)" = "debug-pox.py" ]; thenn export OPT=""n export FLG="--debug"nfinnif [ -x pypy/bin/pypy ]; thenn exec pypy/bin/pypy $OPT "$0" $FLG "$@"nfinnif type python2.7 > /dev/null 2> /dev/null; thenn exec python2.7 $OPT "$0" $FLG "$@"nfinexec 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 : ''
标记化脚本
下面是一个 Python 2.7 脚本,用于标记pox.py脚本:
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))
这是一个可以作为 shell 脚本和Python 脚本执行的文件。请注意,shebang 是#!/bin/sh
的,因此该脚本应首先作为 shell 脚本运行。(我忽略了-
参数,该参数指示sh
应该从标准输入而不是文件中读取。我不太确定它在这里的意义是什么,因为我从未见过这样写的 shebang
。预期的调用类似于./pox.py ...
或sh ./pox.py ...
脚本的第一行是''''true
,在删除引号后与true
相同,因此命令运行并且除了成功退出外什么都不做。以下行是用于确定要使用的 Python 解释器以及要传递给调用的选项的有效命令。三个exec
命令之一
exec pypy/bin/pypy $OPT "$0" $FLG "$@"
exec python2.7 $OPT "$0" $FLG "$@"
exec python $OPT "$0" $FLG "$@"
然后执行与 Python 脚本相同的文件,因此以第二个'''
开头的行永远不会被 shell 看到(这很好,因为由第一个'
开头的单词既不会以最终结束'
结尾,也不会是有效的命令如果它被终止)。"$0"
是当前文件的名称,"$@"
表示脚本的参数(shell 脚本会忽略这些参数,除非传递给 Python 脚本,如下所示)。
一旦脚本作为 Python 脚本运行,''''true
开头的行就会被简单地视为将被忽略的文档字符串的开头。Python 脚本本身很简单
from pox.boot import boot
if __name__ == '__main__':
boot()
至于为什么这一切要从''''true
说起?作为 shell 脚本,您需要有偶数个引号来平衡彼此。但是,只有''''
shell 会尝试将其视为命令的空字符串,并且没有名称为空字符串的命令。 但是,''''true
确实会产生有效的命令。