python3 argparse自动完成失败

Mik*_*nov 0 bash argparse python-3.x

当我在 python3 中使用 arparse 时,我发现了一些奇怪的事情。

#!/usr/bin/env python3

import argparse

def create_parser():
    p = argparse.ArgumentParser(add_help=True)
    p.add_argument('-i', help='i parameter', required=True)
    p.add_argument('-m', help='m parameter', required=True)
    return p

if __name__ == '__main__':
    p = create_parser()
    n = p.parse_args()
    print(n)
Run Code Online (Sandbox Code Playgroud)

当我尝试启动它时

python3 ./script.py -i ./some_folder/some_file -m ./
Run Code Online (Sandbox Code Playgroud)

bash 自动完成与“-i”参数一起工作,但不能与“-m”一起工作。例如,如果我将“-m”重命名为“-me”,则一切正常。

在 bash 中,我尝试使用“-m”参数启动其他命令,但它不仅适用于 argparse。这里哪里会出错?

mat*_*ata 5

这里发生的事情是命令的自动完成python3开始:

$ complete | grep python
complete -F _python python2
complete -F _python python3
complete -F _python python
Run Code Online (Sandbox Code Playgroud)

_python处理它的函数应该是这样的:

$ type _python
_python is a function
_python () 
{ 
    local cur prev words cword;
    _init_completion || return;
    case $prev in 
        -'?' | -h | --help | -V | --version | -c)
            return 0
        ;;
        -m)
            _python_modules "$1";
            return 0
        ;;
        -Q)
            COMPREPLY=($( compgen -W "old new warn warnall" -- "$cur" ));
            return 0
        ;;
        -W)
            COMPREPLY=($( compgen -W "ignore default all module once error"                 -- "$cur" ));
            return 0
        ;;
        !(?(*/)python*([0-9.])|-?))
            [[ $cword -lt 2 || ${words[cword-2]} != -@(Q|W) ]] && _filedir
        ;;
    esac;
    local i;
    for ((i=0; i < ${#words[@]}-1; i++ ))
    do
        if [[ ${words[i]} == -c ]]; then
            _filedir;
        fi;
    done;
    if [[ "$cur" != -* ]]; then
        _filedir 'py?([co])';
    else
        COMPREPLY=($( compgen -W '$( _parse_help "$1" -h )' -- "$cur" ));
    fi;
    return 0
}
Run Code Online (Sandbox Code Playgroud)

完成函数将-m标志作为参数显示为 python 或脚本的相同处理,因此它尝试使用模块名称列表来完成。

解决此问题的一种方法是为python3不会触发完成的命令使用别名,例如:

$ alias py3=python3
Run Code Online (Sandbox Code Playgroud)

为了使这个持久化,你可以把它放在你的~/.bashrc. 然后你可以使用

$ py3 ./script.py -i ./some_folder/some_file -m ./[TAB]
Run Code Online (Sandbox Code Playgroud)

这将使用文件名完成。

或者将-m标志重命名为其他名称。