別のスクリプトからスクリプトを呼び出す最良の方法は何ですか?


307

モジュールにないtest1.pyという名前のスクリプトがあります。スクリプト自体が実行されたときに実行されるコードが含まれているだけです。関数、クラス、メソッドなどはありません。サービスとして実行される別のスクリプトがあります。サービスとして実行されているスクリプトからtest1.pyを呼び出します。

例えば:

ファイルtest1.py

print "I am a test"
print "see! I do nothing productive."

ファイルservice.py

# Lots of stuff here
test1.py # do whatever is in test1.py

私は、ファイルを開いて内容を読み取り、基本的にそれを評価する1つの方法を知っています。これを行うにはもっと良い方法があると思います。または少なくとも私はそう願っています。


42
より良い方法は、メソッドとクラスを記述して使用することです
Aamir


3
runpy.run_moduleまだ回答が投稿されていませんか?!
Aran-Fey

回答:


279

これを行う通常の方法は次のようなものです。

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py

import test1

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

44
test1.py離れたディレクトリにある場合はどうなりますか?
Evgeni Sergeev 2014年


18
これは実際には質問に答えませんが、そうですか?スクリプト全体を実行するのではなく、インポートするスクリプト内からいくつかの関数を実行します。
2017年

2
@GennaroTedesco:間違いです。実際に実行しない全体(のみ定義スクリプトためであろうその場合に)。これはOPがやりたいことのように思えます。この答えはそれだけではありませんが、間違いなく質問に答えます。import test1service.pysome_func()__name__ == '__main__'False
martineau 2017年

2
たとえば、test1.py関数の定義が含まれていない場合(たとえば、some_func()コードの一部の行だけprint("hello"))、コードは機能しません。この特定の例では、後でコールバックする外部関数を本質的にインポートしているため、機能します。
確定

144

これはPython 2で可能です。

execfile("test2.py")

ケースで重要な場合は、名前空間の処理に関するドキュメントを参照してください。

Python 3では、これは(thanks to @fantastory)を使用して可能です

exec(open("test2.py").read())

ただし、別のアプローチの使用を検討する必要があります。あなたのアイデア(私が見ることができるものから)はあまりきれいに見えません。


9
私がpython 32で直接必要とするものはexec(open( 'test2.py')。read())です
ファンタ

8
このアプローチは、呼び出しネームスペース内でスクリプトを実行します。:)
dmvianna 2013年

6
スクリプトにコマンドライン引数を渡すには、sys.argvリストを編集します。
jfs

1
:Pythonの3当量のより包括的な治療stackoverflow.com/questions/436198/...
ジョン・Y

2
これは(PYファイルに渡される)引数を受け入れません!
Apostolos

70

別の方法:

ファイルtest1.py:

print "test1.py"

ファイルservice.py:

import subprocess

subprocess.call("test1.py", shell=True)

この方法の利点は、既存のPythonスクリプトを編集してすべてのコードをサブルーチンに入れる必要がないことです。

ドキュメント:Python 2Python 3


7
私が使用していたsubprocess.call("./test1.py", shell=True)それを動作させるために
asmaier

5
shell=True必要がない限り使用しないでください。
Piotr Dobrogost 2013年

2
@PiotrDobrogost-どの状況が必要になるかを指定できますか?
sancho.s ReinstateMonicaCellio 2013

7
現在のディレクトリがPATHにない一般的なUnixでは機能しません。test1.py実行可能であり、シバン行(#!/usr/bin/env python)があり、フルパスを指定するか、実行可能ファイルを自分で提供する必要がありますここcall([sys.executable, os.path.join(get_script_dir(), 'test1.py')])で、get_script_dir()はここで定義されています
jfs

5
またはsubprocess.call(['python', 'test1.py'])
Big McLargeHuge 2018年

21

test1.pyをservice.py内で呼び出されたときと同じ機能で実行可能にしたい場合は、次のようにします。

test1.py

def main():
    print "I am a test"
    print "see! I do nothing productive."

if __name__ == "__main__":
    main()

service.py

import test1
# lots of stuff here
test1.main() # do whatever is in test1.py

3
ランタイムパラメータがある場合はどうなりますか?
ガブリエルフェア

13
import os

os.system("python myOtherScript.py arg1 arg2 arg3")  

osを使用すると、端末を直接呼び出すことができます。さらに具体的にしたい場合は、入力文字列をローカル変数と連結できます。

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)

への呼び出しos.systemは避けてください。同じことを次のクラスから行うことができますPopen, Call,
user1767754

Pythonのドキュメントから:サブプロセスモジュールは、新しいプロセスを生成してその結果を取得するためのより強力な機能を提供します。この関数を使用するよりも、そのモジュールを使用する方が適切です。
Big McLargeHuge

12

これを行うべきではありません。代わりに、次のようにします。

test1.py:

 def print_test():
      print "I am a test"
      print "see! I do nothing productive."

service.py

#near the top
from test1 import print_test
#lots of stuff here
print_test()

1
test1をインポートすると、ファイルの場所がどのようにしてわかりますか?同じディレクトリにある必要がありますか?そうでない場合はどうなりますか?
NULL。デュードは

8

使用import test1第1回使用のために-それはスクリプトを実行します。後で呼び出す場合は、スクリプトをインポートされたモジュールとして扱い、reload(test1)メソッドを呼び出します。

reload(module)が実行されるとき:

  • Pythonモジュールのコードが再コンパイルされ、モジュールレベルのコードが再実行されて、モジュールのディクショナリの名前にバインドされる新しいオブジェクトのセットが定義されます。拡張モジュールのinit関数が呼び出されていません

の簡単なチェックをsys.modules使用して、適切なアクションを呼び出すことができます。スクリプト名を文字列('test1')として参照し続けるには、組み込みの' import()'を使用します。

import sys
if sys.modules.has_key['test1']:
    reload(sys.modules['test1'])
else:
    __import__('test1')

3
reloadはPython 3で
削除されました

1
モジュールをインポートすることは、それを実行することと同等ではありませんif __name__ == "__main__":。たとえば、guardを検討してください。他にももっと微妙な違いがあるかもしれません。グローバルレベルで任意のコードを残さないでください。それを関数に入れて、代わりに受け入れられた回答で提案されているようにインポート後に呼び出します
jfs

5

私はrunpyが好きです

#!/usr/bin/env python
# coding: utf-8

import runpy

runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')

3

なぜtest1をインポートしないのですか?すべてのpythonスクリプトはモジュールです。より良い方法は、main / runなどの関数をtest1.pyに入れ、test1をインポートしてtest1.main()を実行することです。または、サブプロセスとしてtest1.pyを実行できます。


3

すでに述べたように、 runpyは現在のスクリプトから他のスクリプトまたはモジュールを実行する良い方法です。

ちなみに、トレーサーやデバッガーがこれを行うのはよくあることであり、そのような状況では、ファイルを直接インポートしたり、サブプロセスでファイルを実行したりするような方法は通常機能しません。

またexec、コードの実行にも注意が必要です。run_globalsインポートエラーやその他の問題を回避するには、適切なものを提供する必要があります。詳細runpy._run_codeについては、を参照してください。


0

これはsubprocessライブラリの例です:

import subprocess

python_version = '3'
path_to_run = './'
py_name = '__main__.py'

# args = [f"python{python_version}", f"{path_to_run}{py_name}"]  # Avaible in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]

res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

1
PythonをPythonのサブプロセスとして実行することは、ほとんど正しい解決策とは言えません。サブプロセスを使用するPopen場合は、上位レベルの関数が本当に望んだことを実行できないのでない限り、避けてください。この場合、check_callまたはrun必要なすべてのことを実行しますが、独自のコードの配管を大幅に減らすことができます。
tripleee

0

このプロセスはやや非正統的ですが、すべてのpythonバージョンで機能しますが、

'if'条件内で 'recommend.py'という名前のスクリプトを実行するとします。

if condition:
       import recommend

テクニックは異なりますが、機能します!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.