web-dev-qa-db-ja.com

Pythonでは、インポートされたモジュールのmain()を呼び出すことができますか?

Pythonには、いくつかの関数を定義するmodule myModule.pyと、いくつかのコマンドライン引数を受け取るmain()があります。

通常、このmain()はbashスクリプトから呼び出します。さて、すべてを小さなpackageに入れたいので、単純なbashスクリプトをPythonスクリプトに変えてパッケージに入れることができると思いました。

それで、実際にはどうすればmyModule.pyのmain()関数を呼び出すmain()関数から MyFormerBashScript.pyを呼び出すのか?それさえできますか? argumentsを渡すにはどうすればよいですか?

65
Ricky Robinson

それは単なる機能です。それをインポートして呼び出します:

import myModule

myModule.main()

引数を解析する必要がある場合、2つのオプションがあります。

  • それらをmain()で解析しますが、sys.argvをパラメーターとして渡します(同じモジュール内の以下のすべてのコードmyModule):

    def main(args):
        # parse arguments using optparse or argparse or what have you
    
    if __== '__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 __== '__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引数を渡します。

ここでの秘Theは、モジュールがスクリプトとして使用されていることを検出することです。 pythonファイルをメインスクリプトとして実行すると(python filename.pyimportステートメントは使用されないため、pythonはそのモジュールを呼び出します"__main__" 。しかし、同じfilename.pyコードがモジュール(import filename)として扱われる場合、pythonは代わりにモジュール名としてそれを使用します。どちらの場合も、変数__name__が設定されており、それに対するテストにより、コードの実行方法がわかります。

90
Martijn Pieters

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 __== '__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
30
barry solomon

場合によります。メインコードが次のようにifで保護されている場合:

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

いいえ、自動変数__name__に影響を与えることができないため、Pythonを実行させることはできません。

しかし、すべてのコードが関数内にある場合、可能になる場合があります。試して

import myModule

myModule.main()

これは、モジュールが__all__で自身を保護する場合でも機能します。

from myModule import *mainを表示しない場合があるため、モジュール自体をインポートする必要があります。

21
Aaron Digulla

私も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 __== '__main__':
    import sys
    main(sys.argv[1:])

重要な点は、引数をparse_args関数に渡すことです。後で、メインを使用するには、Martijnの指示どおりに実行します。

2
eguaio

私が探していた答えはここに答えられました: python argparseをsys.argv以外の引数と一緒に使用するには?

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 __== "__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)
1
Sida Zhou

コマンドライン引数も渡そうとしていると仮定します。

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