在Python中,我有一个模块 myModule.py,其中我定义了一些函数和一个main(),它需要一些命令行参数。
我通常从 bash 脚本中调用它 main()。现在,我想把所有东西都放到一个小包里,所以我想也许我可以把我简单的bash脚本变成一个Python脚本,然后把它放在包里。
那么,我如何从 MyFormerBashScript.py 的 main() 函数实际调用 myModule.py 的 main() 函数呢?我能做到吗?如何将任何参数传递给它?
这只是一个函数。导入并调用它:
import myModule
myModule.main()
如果需要解析参数,有两个选项:
在
main()
中解析它们,但传入sys.argv
作为参数(以下所有代码在同一模块中myModule
):def main(args): # parse arguments using optparse or argparse or what have you if __name__ == '__main__': import sys main(sys.argv[1:])
现在,您可以从其他模块导入和调用
myModule.main(['arg1', 'arg2', 'arg3'])
。main()
接受已解析的参数(再次接受myModule
模块中的所有代码):def main(foo, bar, baz='spam'): # run with already parsed arguments if __name__ == '__main__': import sys # parse sys.argv[1:] using optparse or argparse or what have you main(foovalue, barvalue, **dictofoptions)
并在其他地方导入和调用
myModule.main(foovalue, barvalue, baz='ham')
,并根据需要传入 python 参数。
这里的诀窍是检测你的模块何时被用作脚本;当你运行一个python文件作为主脚本(python filename.py
)时,没有使用import
语句,所以python调用该模块"__main__"
。但是,如果将相同的filename.py
代码视为模块(import filename
),则python将其用作模块名称。在这两种情况下,都设置了变量__name__
,针对该变量进行测试会告诉您代码是如何运行的。
> Martijen的回答是有道理的,但它遗漏了一些对其他人来说似乎很明显但对我来说很难弄清楚的关键。
在使用 argparse 的版本中,您需要在主体中包含此行。
args = parser.parse_args(args)
通常,当您仅在脚本中使用argparse时,您只需编写即可
args = parser.parse_args()
parse_args从命令行找到参数。但是在这种情况下,main 函数无法访问命令行参数,因此您必须告诉 argparse 参数是什么。
这是一个例子
import argparse
import sys
def x(x_center, y_center):
print "X center:", x_center
print "Y center:", y_center
def main(args):
parser = argparse.ArgumentParser(description="Do something.")
parser.add_argument("-x", "--xcenter", type=float, default= 2, required=False)
parser.add_argument("-y", "--ycenter", type=float, default= 4, required=False)
args = parser.parse_args(args)
x(args.xcenter, args.ycenter)
if __name__ == '__main__':
main(sys.argv[1:])
假设您命名了此 mytest.py要运行它,您可以从命令行执行其中任何一个操作
python ./mytest.py -x 8
python ./mytest.py -x 8 -y 2
python ./mytest.py
分别返回
X center: 8.0
Y center: 4
或
X center: 8.0
Y center: 2.0
或
X center: 2
Y center: 4
或者如果你想从另一个python脚本运行,你可以这样做
import mytest
mytest.main(["-x","7","-y","6"])
返回
X center: 7.0
Y center: 6.0
这取决于。如果主代码受if
保护,如下所示:
if __name__ == '__main__':
...main code...
那么不,你不能让 Python 执行它,因为你不能影响自动变量__name__
。
但是当所有代码都在一个函数中时,那么也许可以。尝试
import myModule
myModule.main()
即使模块使用__all__
保护自身,这也有效。
from myModule import *
可能不会让您看到main
,因此您确实需要导入模块本身。
我正在寻找的答案在这里得到了回答:如何将python argparse与sys.argv以外的args一起使用?
如果main.py
和parse_args()
以这种方式编写,那么解析可以很好地完成
# main.py
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="")
parser.add_argument('--input', default='my_input.txt')
return parser
def main(args):
print(args.input)
if __name__ == "__main__":
parser = parse_args()
args = parser.parse_args()
main(args)
然后,您可以在另一个 python 脚本中调用 main()
并使用parser.parse_args(['--input', 'foobar.txt'])
解析参数:
# temp.py
from main import main, parse_args
parser = parse_args()
args = parser.parse_args([]) # note the square bracket
# to overwrite default, use parser.parse_args(['--input', 'foobar.txt'])
print(args) # Namespace(input='my_input.txt')
main(args)
我也同样需要使用argparse
。事情是parse_args
argparse.ArgumentParser
对象实例的函数默认从sys.args
中隐式获取其参数。按照 Martijn 路线,解决方法包括使其明确,因此您可以根据需要更改传递给parse_args
的参数。
def main(args):
# some stuff
parser = argparse.ArgumentParser()
# some other stuff
parsed_args = parser.parse_args(args)
# more stuff with the args
if __name__ == '__main__':
import sys
main(sys.argv[1:])
关键点是将参数传递给parse_args
函数。以后,要使用主要内容,您只需按照 Martijn 所说的进行操作即可。
假设您也尝试传递命令行参数。
import sys
import myModule
def main():
# this will just pass all of the system arguments as is
myModule.main(*sys.argv)
# all the argv but the script name
myModule.main(*sys.argv[1:])
我遇到了这个问题,我无法调用文件Main()
方法,因为它用这些单击选项装饰,例如:
# @click.command()
# @click.option('--username', '-u', help="Username to use for authentication.")
当我删除这些装饰/属性时,我可以从另一个文件中成功调用 Main() 方法。
from PyFileNameInSameDirectory import main as task
task()