在 Python 中,我可以调用导入模块的 main()吗?

在 Python 中,我有一个 模组 myModule.py,其中定义了几个函数,还有一个 主(),它接受几个命令行参数。

我通常从 bash 脚本调用 main ()。现在,我想把所有东西都放到一个小的 包裹中,所以我想也许我可以把我的简单 bash 脚本转换成 Python 脚本,并把它放到包中。

那么,我该如何实际操作 myModule.py 的 myformerbashscript.py 的 调用 main ()函数呢?我能做到吗?我如何传递任何 争论给它?

161681 次浏览

它只是一个函数,导入并调用它:

import myModule


myModule.main()

If you need to parse arguments, you have two options:

  • 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'])

  • Have main() accept parameters that are already parsed (again all code in the myModule module):

    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__,并且针对它进行测试将告诉您代码是如何运行的。

It depends. If the main code is protected by an if as in:

if __name__ == '__main__':
...main code...

那么不行,你不能让 Python 执行它,因为你不能影响自动变量 __name__

但是当所有的代码都在一个函数中时,那么也许可以做到这一点

import myModule


myModule.main()

这甚至在模块使用 __all__保护自己时也可以工作。

from myModule import *可能不会使 main对您可见,因此您确实需要导入模块本身。

假设您也尝试传递命令行参数。

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:])

我也同样需要使用 argparseargparse.ArgumentParser对象实例的 parse_args函数默认情况下隐式地从 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:])

关键是将 args 传递给 parse_args函数。 后来,使用主,你只是按照马丁告诉。

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 To run it you can either do any of these from the command line

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"])

which returns

X center: 7.0
Y center: 6.0

我寻找的答案在这里得到了回答: 如何对 sys.argv 以外的参数使用 python argparse?

如果以这种方式编写 main.pyparse_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)

然后,您可以调用 main(),并在另一个 python 脚本中使用 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)

我遇到了这个问题,我不能调用文件 Main()方法,因为它用这些点击选项装饰,例如:

# @click.command()
# @click.option('--username', '-u', help="Username to use for authentication.")

当我删除这些修饰/属性时,我可以成功地从另一个文件调用 Main ()方法。

from PyFileNameInSameDirectory import main as task
task()