113

在 Python 中,我有一个模块myModule.py ,我在其中定义了一些函数和一个main(),它接受一些命令行参数。

我通常从 bash 脚本中调用这个 main()。现在,我想把所有东西都放在一个小包里,所以我想也许我可以把我简单的 bash 脚本变成 Python 脚本,然后放在包里。

那么,我如何真正从MyFormerBashScript.py的 main() 函数调用myModule.py的 main() 函数?我什至可以这样做吗?我如何将任何参数传递给它?

4

7 回答 7

139

这只是一个功能。导入并调用它:

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__设置,并且针对该变量进行测试会告诉您代码是如何运行的。

于 2013-01-24T11:26:23.580 回答
49

Martijen 的回答是有道理的,但它遗漏了一些对其他人来说似乎很明显但我很难弄清楚的关键内容。

在您使用 argparse 的版本中,您需要在主体中包含这一行。

args = parser.parse_args(args)

通常,当您仅在脚本中使用 argparse 时,您只需编写

args = parser.parse_args()

和 parse_args 从命令行查找参数。但在这种情况下,主函数无法访问命令行参数,因此您必须告诉 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
于 2016-05-10T17:14:31.873 回答
32

这取决于。如果主代码受如下保护if

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

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

但是当所有代码都在一个函数中时,也许可以。尝试

import myModule

myModule.main()

即使模块使用__all__.

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

于 2013-01-24T11:30:55.573 回答
3

我也有同样的需要argparse。对象实例的函数默认parse_args从. 遵循 Martijn 线的解决方法包括明确说明,因此您可以根据需要更改传递给的参数。argparse.ArgumentParsersys.argsparse_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函数。稍后,要使用 main,您只需按照 Martijn 的说明进行操作。

于 2014-12-03T11:53:15.190 回答
3

我正在寻找的答案在这里得到了回答:How to use python argparse with args than sys.argv?

如果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)

然后你可以在另一个 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)
于 2017-12-01T03:17:42.800 回答
0

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

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:])
于 2013-01-24T11:31:09.550 回答
0

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

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

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

from PyFileNameInSameDirectory import main as task
task()
于 2021-05-31T04:32:42.937 回答