将python函数作为bash命令运行

2024-06-01 08:12:30 发布

您现在位置:Python中文网/ 问答频道 /正文

关于如何从python运行shell命令有很多文献,但是我有兴趣做相反的事情。我有一个python模块mycommands.py,它包含如下函数

def command(arg1, arg2):
    pass

def command1(arg1, arg2, arg3):
    pass

其中函数参数都是字符串。目标是能够从bash运行这些函数,如下所示

$ command arg1 arg2 
$ command1 arg1 arg2 arg3 

到目前为止,我在.bash\u 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)"
}

如果有一个bash命令

$ import_python mycommands.py

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


Tags: 模块函数pyimport命令bashdefpass
3条回答

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

command sub-command arg1 args2

从贝壳里。

请参阅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

使用多个子命令,您可以在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)

您可以这样使用它(假设您的$PATH中有一个名为cmd.py的可执行Python脚本):

$ 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

NB:以上是一个非常简单的示例,演示如何在shell中使用eval

可以使用参数运行脚本,然后执行以下操作:

(f1不带参数调用,f2带2个参数调用。错误处理还不是傻瓜证明。)

import sys

def run():
    if len(sys.argv)<2:
        error()
        return

    if sys.argv[1] == 'f1':
        f1()

    elif sys.argv[1] == 'f2':
        if(len(sys.argv)!=4):
            error()
            return
        f2(sys.argv[2],sys.argv[3])

    else:
        error()

def f1():
    print("f1")

def f2(a,b):
    print("f2, arguments:",a,b)

def error():
    print("error")

run()

这不允许你调用

commmand arg1 arg2

但你可以

python test.py f1
python test.py f2 arg1 arg2

编辑:

您可以创建别名:

alias f1="python test.py f1"
alias f1="python test.py f2"

为了达到你的要求:

$ f1
$ f2 arg1 arg2

您可以创建一个基本脚本,例如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:])

然后可以创建指向此脚本的软链接:

ln -s command.py command1
ln -s command.py command2

最后测试一下:

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

$ ./command2 world
Command2
('world',)

相关问题 更多 >