我有这样的代码:

def hello():
    return 'Hi :)'

我如何直接从命令行运行它?


当前回答

从myfile导入hello;hello() `,其中myfile必须替换为Python脚本的基名。(例如,myfile.py变成myfile)。

但是,如果hello()是Python脚本中的“永久”主入口点,那么通常的方法如下:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

这允许您通过运行python myfile.py或python -m myfile来执行脚本。

这里解释一下:__name__是一个特殊的Python变量,保存当前正在执行的模块的名称,除非从命令行启动模块,在这种情况下,它会变成"__main__"。

其他回答

我写了一个快速的小Python脚本,可以从bash命令行调用。它接受你想要调用的模块、类和方法的名称,以及你想要传递的参数。我把它叫做PyRun,并去掉了.py扩展名,让它可以用chmod +x PyRun执行,这样我就可以像下面这样快速地调用它:

./PyRun PyTest.ClassName.Method1 Param1

将其保存在一个名为PyRun的文件中

#!/usr/bin/env python
#make executable in bash chmod +x PyRun

import sys
import inspect
import importlib
import os

if __name__ == "__main__":
    cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
    if cmd_folder not in sys.path:
        sys.path.insert(0, cmd_folder)

    # get the second argument from the command line      
    methodname = sys.argv[1]

    # split this into module, class and function name
    modulename, classname, funcname = methodname.split(".")

    # get pointers to the objects based on the string names
    themodule = importlib.import_module(modulename)
    theclass = getattr(themodule, classname)
    thefunc = getattr(theclass, funcname)

    # pass all the parameters from the third until the end of 
    # what the function needs & ignore the rest
    args = inspect.getargspec(thefunc)
    z = len(args[0]) + 2
    params=sys.argv[2:z]
    thefunc(*params)

下面是一个示例模块来展示它是如何工作的。它被保存在一个名为PyTest.py的文件中:

class SomeClass:
 @staticmethod
 def First():
     print "First"

 @staticmethod
 def Second(x):
    print(x)
    # for x1 in x:
    #     print x1

 @staticmethod
 def Third(x, y):
     print x
     print y

class OtherClass:
    @staticmethod
    def Uno():
        print("Uno")

试着运行这些例子:

./PyRun PyTest.SomeClass.First
./PyRun PyTest.SomeClass.Second Hello
./PyRun PyTest.SomeClass.Third Hello World
./PyRun PyTest.OtherClass.Uno
./PyRun PyTest.SomeClass.Second "Hello"
./PyRun PyTest.SomeClass.Second \(Hello, World\)

请注意最后一个转义圆括号的例子,将一个元组作为第二个方法的唯一参数传递给第二个方法。

如果传递的参数少于方法所需的参数,就会报错。如果你传递太多,它会忽略额外的部分。该模块必须在当前工作文件夹中,放置PyRun可以在你路径的任何位置。

从myfile导入hello;hello() `,其中myfile必须替换为Python脚本的基名。(例如,myfile.py变成myfile)。

但是,如果hello()是Python脚本中的“永久”主入口点,那么通常的方法如下:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

这允许您通过运行python myfile.py或python -m myfile来执行脚本。

这里解释一下:__name__是一个特殊的Python变量,保存当前正在执行的模块的名称,除非从命令行启动模块,在这种情况下,它会变成"__main__"。

此函数不能从命令行运行,因为它返回的值将不被传递。您可以删除返回并使用print代替

只要把hello()放在函数下面的某个地方,它就会在你执行python your_file.py时执行

为了一个更简洁的解决方案,你可以使用这个:

if __name__ == '__main__':
    hello()

这样,函数只会在运行文件时执行,而不会在导入文件时执行。

这个脚本类似于这里的其他答案,但它也列出了可用的函数,带有参数和文档字符串:

"""Small script to allow functions to be called from the command line.
Run this script without argument to list the available functions:

    $ python many_functions.py
    Available functions in many_functions.py:

    python many_functions.py a  : Do some stuff

    python many_functions.py b  : Do another stuff

    python many_functions.py c x y : Calculate x + y

    python many_functions.py d  : ?

Run this script with arguments to try to call the corresponding function:

    $ python many_functions.py a
    Function a

    $ python many_functions.py c 3 5
    3 + 5 = 8

    $ python many_functions.py z
    Function z not found
"""

import sys
import inspect

#######################################################################
#                         Your functions here                         #
#######################################################################

def a():
    """Do some stuff"""
    print("Function a")

def b():
    """Do another stuff"""
    a()
    print("Function b")

def c(x, y):
    """Calculate x + y"""
    print(f"{x} + {y} = {int(x) + int(y)}")

def d():
    # No doc
    print("Function d")

#######################################################################
#         Some logic to find and display available functions          #
#######################################################################

def _get_local_functions():
    local_functions = {}
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isfunction(obj) and not name.startswith('_') and obj.__module__ == __name__:
            local_functions[name] = obj
    return local_functions

def _list_functions(script_name):
    print(f"Available functions in {script_name}:")
    for name, f in _get_local_functions().items():
        print()
        arguments = inspect.signature(f).parameters
        print(f"python {script_name} {name} {' '.join(arguments)} : {f.__doc__ or '?'}")


if __name__ == '__main__':
    script_name, *args = sys.argv
    if args:
        functions = _get_local_functions()
        function_name = args.pop(0)
        if function_name in functions:
            function = functions[function_name]
            function(*args)
        else:
            print(f"Function {function_name} not found")
            _list_functions(script_name)
    else:
        _list_functions(script_name)

运行不带参数的脚本列出可用的函数:

$ python many_functions.py
Available functions in many_functions.py:

python many_functions.py a  : Do some stuff

python many_functions.py b  : Do another stuff

python many_functions.py c x y : Calculate x + y

python many_functions.py d  : ?

运行这个带有参数的脚本,尝试调用相应的函数:

$ python many_functions.py a
Function a

$ python many_functions.py c 3 5
3 + 5 = 8

$ python many_functions.py z
Function z not found