将python函数作为bash命令运行

dzh*_*lil 13 python bash shell

有很多关于如何从python运行shell命令的文献,但我感兴趣的是反过来.我有一个python模块mycommands.py,其中包含如下所示的函数

def command(arg1, arg2):
    pass

def command1(arg1, arg2, arg3):
    pass
Run Code Online (Sandbox Code Playgroud)

其中函数参数都是字符串.目标是能够从下面的bash运行这些函数

$ command arg1 arg2 
$ command1 arg1 arg2 arg3 
Run Code Online (Sandbox Code Playgroud)

到目前为止,我在.bash_profile中有以下粗暴设置,我必须手动为每个python函数提供bash绑定

function command() {
    python -c "import mycommand as m; out=m.command('$1', '$2'); print(out)"
}

function command1() {
    python -c "import mycommand as m; out=m.command1('$1', '$2', '$3'); print(out)"
}
Run Code Online (Sandbox Code Playgroud)

如果一个人可以拥有一个bash命令就好了

$ import_python mycommands.py
Run Code Online (Sandbox Code Playgroud)

它将自动导入模块中的所有python函数作为bash命令.是否存在实现此类命令的库?

Jun*_*sor 7

您可以创建一个基本脚本,让我们说command.py一下这个脚本被调用的名称(不要忘记让它可执行):

#!/usr/bin/python
import os.path
import sys

def command1(*args):
    print 'Command1'
    print args

def command2(*args):
    print 'Command2'
    print args


commands = {
    'command1': command1,
    'command2': command2
}

if __name__ == '__main__':
    command = os.path.basename(sys.argv[0])
    if command in commands:
        commands[command](*sys.argv[1:])
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建此脚本的软链接:

ln -s command.py command1
ln -s command.py command2
Run Code Online (Sandbox Code Playgroud)

最后测试一下:

$ ./command1 hello
Command1
('hello',)

$ ./command2 world
Command2
('world',)
Run Code Online (Sandbox Code Playgroud)


小智 5

根据您的实际使用情况,最佳解决方案可能是简单地使用Click(或至少argparse标准库中的模块)来构建您的Python脚本并将其称为

command sub-command arg1 args2
Run Code Online (Sandbox Code Playgroud)

从壳.

请参阅Mercurial,了解其中一个突出的例子.

如果您确实必须将命令作为第一级shell命令,请使用符号链接或别名,如其他答案中所述.

只需几个方法,您可以进行符号链接和调度sys.argv[0]:

$ cat cmd.py 
#!/usr/bin/env python

if __name__ == '__main__':
    import sys
    from os.path import basename
    cmd = basename(sys.argv[0])
    print("This script was called as " + cmd)

$ ln -s cmd.py bar
$ ln -s cmd.py foo
$ ./foo 
This script was called as foo
$ ./bar
This script was called as bar
Run Code Online (Sandbox Code Playgroud)

使用多个子命令,您可以在Python脚本中添加以下内容以"自动化"该过程:

#!/usr/bin/env python
import sys

def do_repeat(a, b):
    print(a*int(b))

def do_uppercase(args):
    print(''.join(args).upper())

def do_eval():
    print("alias repeat='python cmd.py repeat';")
    print("alias uppercase='python cmd.py uppercase';")

if __name__ == '__main__':
    cmd = sys.argv[1]
    if cmd=='--eval':
        do_eval()

    else:
        args = sys.argv[2:]
        if cmd=='repeat':
            do_repeat(*args)
        elif cmd=='uppercase':
            do_uppercase(args)
        else:
            print('Unknown command: ' + cmd)
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它(假设cmd.py你的某个地方有一个可执行的Python脚本$PATH):

$ cmd.py --eval          # just to show what the output looks like
alias repeat='python cmd.py repeat';
alias uppercase='python cmd.py uppercase';

$ eval $(python cmd.py --eval)  # this would go in your .bashrc
$ repeat asdf 3
asdfasdfasdf
$ uppercase qwer
QWER
Run Code Online (Sandbox Code Playgroud)

注意:上面是一个非常基本的例子,展示了如何eval在shell中使用.