我有这样的代码:
def hello():
return 'Hi :)'
我如何直接从命令行运行它?
我有这样的代码:
def hello():
return 'Hi :)'
我如何直接从命令行运行它?
当前回答
在命令行上使用python命令输入python始终是一个选项
然后导入您的文件,因此导入example_file
然后使用example_file.hello()运行命令
这避免了每次运行python -c等时突然出现的奇怪的.pyc复制函数。
也许不像单个命令那么方便,但是从命令行文本文件的一个很好的快速修复,并允许您使用python来调用和执行您的文件。
其他回答
将此代码片段添加到脚本底部
def myfunction():
...
if __name__ == '__main__':
globals()[sys.argv[1]]()
现在可以通过运行来调用函数
python myscript.py myfunction
这是因为您将命令行参数(函数名的字符串)传递到locals中,locals是一个包含当前局部符号表的字典。最后的parantheses将使函数被调用。
更新:如果你想让函数从命令行接受一个参数,你可以传入sys。Argv[2]像这样:
def myfunction(mystring):
print(mystring)
if __name__ == '__main__':
globals()[sys.argv[1]](sys.argv[2])
这样,运行python myscript.py myfunction "hello"将输出hello。
让我们简单一点,使用一个模块。
尝试:pip安装compago
然后写:
import compago
app = compago.Application()
@app.command
def hello():
print "hi there!"
@app.command
def goodbye():
print "see ya later."
if __name__ == "__main__":
app.run()
然后用like so:
$ python test.py hello
hi there!
$ python test.py goodbye
see ya later.
注意:目前在Python 3中有一个bug,但在Python 2中工作得很好。
编辑:一个更好的选择,在我看来是模块fire谷歌,它可以很容易地传递函数参数。它安装有pip安装火。来自他们的GitHub:
这里有一个简单的例子。
import fire
class Calculator(object):
"""A simple calculator class."""
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
然后,从命令行,你可以运行:
python calculator.py double 10 # 20
python calculator.py double --number=15 # 30
就像这样: call_from_terminal.py
# call_from_terminal.py
# Ex to run from terminal
# ip='"hi"'
# python -c "import call_from_terminal as cft; cft.test_term_fun(${ip})"
# or
# fun_name='call_from_terminal'
# python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
def test_term_fun(ip):
print ip
这在bash中工作。
$ ip='"hi"' ; fun_name='call_from_terminal'
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi
这个脚本类似于这里的其他答案,但它也列出了可用的函数,带有参数和文档字符串:
"""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
我写了一个快速的小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可以在你路径的任何位置。