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


87

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

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

だから、どのように私は実際にはない、メイン()を呼び出しmyModule.pyの機能をmain()関数からMyFormerBashScript.pyの?私もそれをすることができますか?引数を渡すにはどうすればよいですか?


myModuleをインポートした場合は、を呼び出すことができるはずmyModule.main()です。これまでに何を試しましたか?
マリウス

私は通常シェルスクリプトから渡す入力引数が心配です。
リッキーロビンソン

subprocessモジュールで呼び出すのは意味がありますか?
BenDundee 2013年

ええ、もっと簡単だと思います。
リッキーロビンソン

回答:


116

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

import myModule

myModule.main()

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

  • それらをで解析しますが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__が設定され、それに対してテストすると、コードがどのように実行されたかがわかります。


3
承知しました。しかし、入力引数はどうですか?私はを使用argparseしているので、端末からスクリプトを呼び出すときは、を使用します$ python myModule -a input_a -b input_b --parameterC input_c。Pythonコード内からどのように機能しますか?それは私が単純な検索から見つけることができなかったものです。
リッキーロビンソン

@RickyRobinson:両方の方法で使用できることを示すために拡張されました。解析された引数または解析される引数を渡すだけです。
MartijnPieters

1
ありがとう。どのコードの抜粋がどのモジュールまたはスクリプトに属しているかも指定していただけますか?最初に思っていたよりもずっと面倒に見えます。
リッキーロビンソン

@RickyRobinson:両方の抜粋は同じモジュールに一緒に属しています。私はそれを明示しました。
MartijnPieters

42

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

4
これはまさに私が必要としていたものです-有益な補遺をありがとうございました
HFBrowning 2017

これはAttributeError: module 'sqlacodegen' has no attribute 'main'
Python2で

26

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

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

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

しかし、すべてのコードが関数内にある場合、それができる可能性があります。試してみてください

import myModule

myModule.main()

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

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


わかりました、説明してくれてありがとう。すべてをmain()関数に入れたので、問題ないはずです。この「2番目の」メインに入力引数を渡す方法についてもっと心配しています。そうする簡単な方法はありますか?
リッキーロビンソン

確かに:import sys; module.main(sys.argv);
Aaron Digulla 2013年

これは__main__私を助けてくれたアクセスについての素晴らしい代替説明です、ありがとう@AaronDigulla
チャーリーG

ここでは別の関数からメインを呼び出すためのトリックがある:stackoverflow.com/a/20158605/3244382
PatriceG

3

私も同じように使う必要があり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が言うように行います。


3

私が探していた答えはここで答えられました:sys.argv以外のargsで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)

次に、別の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)

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

ありがとう。私は実際にのargparse代わりに使用していますsys.argv。この場合、どのように変化しますか?また、外部スクリプトから、ユーザーが入力するいくつかの入力引数を渡したいだけですが、内部スクリプト(myModule.py)の他の入力引数は私がハードコーディングしています。
リッキーロビンソン

コード自体を見ずに、詳細に答えるのは難しいです。一般に、引数を渡すだけです。*配列アンパックf(a) => f([1,2,3])f(*a) => f(1,2,3) あなたは同じように簡単に行うことができますmyModule.main(sys.argv[1], "other value", 39)または何を。
agoebel 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.