Python sys.argv[1:]未识别命令行选项
更新/解决方案:答案在下面,来自 Zack。问题确实出在脚本文件 clenotes.cmd 上的 DOS 换行符。因为我对各种文件进行了很多操作,所以我删除了整个目录,然后从 这里 重新下载了一个新的副本。我像这样在文件上运行了 Zack 的 perl 脚本:
perl -pi.bak -e 's/[ \t\r]+$//' clenotes.cmd
然后我稍微修改了一下命令执行,最终的脚本变成了:
CWD=`dirname $0`
JYTHON_HOME="$CWD"
LIB_DIR="$JYTHON_HOME/lib"
NOTES_HOME="/opt/ibm/lotus/notes/"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NOTES_HOME
java -cp "$LIB_DIR" -jar "$LIB_DIR/jython.jar" -Djython.home="$CWD/" -Dpython.path="$LIB_DIR:$CWD/ext" -Djava.library.path="$NOTES_HOME" "$LIB_DIR/clenotes/cletes/clenotes.py" "$@"
就这样——其他一切都正常工作。clenotes.py 或 clenotes.cfg 不需要任何修改。非常感谢大家耐心等待这个问题,我想这其实是个很简单的事情。
更新:我在减少一些代码,以使其更易读,并去掉帖子中不必要的信息。
我正在尝试让 Lotus Notes 命令行 在 Linux 上运行,但在 python 文件中遇到了与 sys.argv[1:] 相关的问题。Windows 脚本在这里:
@echo off
@setlocal
set CWD=%~dp0
set JYTHON_HOME=%CWD%
set LIB_DIR=%JYTHON_HOME%/lib
java -cp %LIB_DIR% -jar %LIB_DIR%/jython.jar -Djython.home=%CWD% -python.path=%LIB_DIR%;%CWD%/ext %LIB_DIR%/clenotes/clenotes.py %*
@endlocal
我在处理变量时遇到了困难,所以在 Linux 上,它看起来就是这样:
java -cp ./lib/ -jar ./lib/jython.jar -Djython.home=./ -Dpython.path=./lib:./ext -Djava.library.path=/opt/ibm/lotus/notes/ ./lib/clenotes/clenotes.py $*
我是在目录内运行它的。无论如何,让我困惑的是,它没有识别我从命令行传递的任何选项。clenotes.cmd --help
的结果是
No commands specified. Use --help option for usage.
这是命令行参数应该被解析的部分:
def main():
Output.log("Entering %s v%s" % (PROGRAM_NAME,VERSION),Output.LOGTYPE_DEBUG)
cliOptions2=[]
for opt in cliOptions:
opt2=opt.replace('--','')
opt2=opt2.replace('!','=')
cliOptions2.append(opt2)
opts=[]
args=[]
try:
opts, args = getopt.getopt(sys.argv[1:], '', cliOptions2)
我在 Arch Linux 64 位的 32 位 chroot 环境中使用 Python 3.1.3。我还需要提供其他信息吗?
以防需要... 这里 是整个 clenotes.py 文件。
此外,按照评论中的要求,配置文件(包含帮助信息和可用选项/参数)在 这里
更新
经过很多尝试,我取得的最佳进展是检查它在(主)方法中设置的 opts 和 args。最令人惊讶的是,当传递一个参数并查看其解析结果时,使用 print sys.argv
,选项后面会带有一个 \r
。例如:
clenotes.cmd appointments
args is ['appointments\r']
在 Windows 上我做了同样的事情,args 被报告为 ['appointments']
。此外,手动设置 args=['appointments']
然后注释掉 getopt.getopt
分配值的部分也能正常工作。
最后,我发现当使用多个参数时,n-1 个参数会被解析并使用,而第 n 个参数会被忽略。这算是一种变通方法,因为我实际上可以使用这个脚本……但显然这不是首选。如果我想查看今天的预约,我可以执行 clenotes.cmd appointments --today --today
,它会正常工作。sys.argv
会输出:['appointments', '--today', '--today\r']
。
那么……是什么导致了尾部的 \r
?我觉得这可能与实际脚本有关。再注意一下:
java -cp ./lib/ -jar ./lib/jython.jar -Djython.home=./ -Dpython.path=./lib:./ext -Djava.library.path=/opt/ibm/lotus/notes/ ./lib/clenotes/clenotes.py $*
所以……一堆路径的东西,然后是实际的 python 文件:clenotes.py $*
我从 这里 得到了 $*
它是不是在捡起回车符??
2 个回答
我还得继续找找看那个 \r 是从哪里来的。不过在此之前,这个问题变得简单多了。一旦参数解析完,就这样做:
args = [arg.strip() for arg in args]
这样就能去掉 \r
了。
编辑:等等——这只是部分解决方案吗?选项还是解析不正确吗?
编辑2:看起来 \r
需要更早去掉。当没有命令的时候,\r
根本没被去掉,因为上面的代码只是在 getopt
完成后才去掉 \r
。这本该是我之前就能想到的——而不是在这里传递 sys.argv[1:]
。
opts, args = getopt.getopt(sys.argv[1:], '', cliOptions2)
先修改它
argv = [arg.strip() for arg in sys.argv[1:]]
opts, args = getopt.getopt(argv, '', cliOptions2)
你也可以直接用 sys.argv[-1] = sys.argv[-1].strip()
... 不过作为一个C语言程序员,我看到这个有点不舒服。我知道这可能有点无理。
或者就按照Zack说的,把clenotes.cmd转换成Linux格式——不过要注意,这样去掉会确保其他人不需要再解决同样的问题。(另一方面,这样做有点丑,或者至少对不期待这种问题的人来说有点神秘。)
我觉得你的问题是因为 clenotes.cfg
文件使用了 DOS 格式的换行符,而 Python 误解了这个格式。试着把 clenotes.py
里的这一行改成:
config.readfp(open('%sconfig/clenotes.cfg' % System.getProperty('jython.home')))
这样读取
config.readfp(open('%sconfig/clenotes.cfg' % System.getProperty('jython.home'), "rU"))
这里的 "rU" 是告诉 Python,虽然它是在 Unix 系统上运行,但它需要准备好处理包含 DOS 格式换行符的文件。你可以查看这个链接 http://docs.python.org/library/functions.html#open,向下滚动到以 "除了标准的 fopen()
模式..." 开头的段落。
(或者你可以运行这个命令: perl -pi.bak -e 's/[ \t\r]+$// clenotes.cfg
-- 这会把文件转换成 Unix 格式的换行符。如果我是你,我可能会同时做这两件事。)
(如果以上建议都没有帮助,我会尝试用上面的 perl 命令直接处理 clenotes.py
文件。我不认为这会是问题,但如果 \r
字符不是来自 clenotes.cfg
,那么 .py
文件就是唯一可能的来源。)
(编辑:根据你在问题中的评论,我现在认为需要把 clenotes.cmd
这个外壳脚本也从 DOS 格式转换成 Unix 格式的换行符。)