91863


まず、マクロ用に作られた、関数化のされてない、シンプルな記述のa.pyと言うファイルがあるとします。  
a.pyは適当な外部に存在し、変更が許されていません。

[code]

    # a.py  C:\tem\a.py
    print("a is")
    print("executed!")
    
[/code]

このa.pyを、b.pyから条件によって呼び出したいと考えています。  
流れとしては、

[code]

    # b.py
    i = int(input())
    
    if i==1:
        実行(a.py) # 外部にあるa.pyを、ここに記述されているかの如く実行したい
    else:
        print("None")
    
[/code]

のようなことをしたいのですが、可能でしょうか。  
お知恵拝借できましたら大変幸いです。


CC BY-SA 4.0
2022-10-27T07:40:36.707
91860
2022-10-28T06:11:47.530
2022-10-28T06:11:47.530
3060
46877
question
python windows
Python スクリプトから外部の .py ファイルを実行する方法は？


可能です。  
import文の本来の使い方とは異なると思いますが、`import a`でa.pyが呼び出せます。  
a.pyとb.pyを同じフォルダに配置する必要があります。

[code]

    #b.py
    i = int(input())
    if i==1:
        #実行(a.py) # 外部にあるa.pyを、ここに記述されているかの如く実行したい
        import a
    else:
        print("None")
    
[/code]

temp以外でb.pyを実行する場合は、a.pyのパスを追加設定する必要があります。

[code]

    #b.py
    i = int(input())
    
    if i==1:
        #実行(a.py) # 外部にあるa.pyを、ここに記述されているかの如く実行したい
        import sys
        sys.path.append('c:\\temp')
        import a
    else:
        print("None")
    
[/code]


CC BY-SA 4.0
2022-10-27T08:50:58.993
91862
2022-10-27T08:50:58.993
35558
91860
answer


直に実行しているように見える方法がこちら。  
[exec(object[, globals[,
locals]])](https://docs.python.org/ja/3.7/library/functions.html#exec)

> この関数は Python コードの動的な実行をサポートします。 object
> は文字列かコードオブジェクトでなければなりません。文字列なら、その文字列は一連の Python 文として解析され、そして (構文エラーが生じない限り)
> 実行されます。

[別の Python スクリプトで execfile() メソッドを使用して Python
スクリプトを実行する](https://www.delftstack.com/ja/howto/python/python-run-another-
python-script/#%E5%88%A5%E3%81%AE-
python-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A7-execfile-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6-python-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)

> execfile() 関数は、インタープリターで目的のファイルを実行します。この関数は Python 2 でのみ機能します。Python 3
> では、execfile() 関数が削除されましたが、Python 3 でも exec() メソッドを使用して同じことが実現できます。

>
[code]

>     exec(open("Script1.py").read())
>  
[/code]

該当の部分を以下のように記述すれば出来るでしょう。  
必要ならばglobal変数やlocal変数の辞書をパラメータに指定することも出来るでしょう。

[code]

    if i==1:
        # 外部にあるa.pyを、ここに記述されているかの如く実行したい
        exec(open(r'C:\tem\a.py','r', newline='', encoding='utf8').read())
    else:
        print("None")
    
[/code]


CC BY-SA 4.0
2022-10-27T10:05:58.353
91863
2022-10-27T10:05:58.353
26370
91860
answer


python
3.6から[`importlib.util.spec_from_file_location`](https://docs.python.org/ja/3/library/importlib.html#importlib.util.spec_from_file_location)を使ってフルパスでモジュールを呼び出せるようになりました。

**サンプルコード**

`module_name`は任意のモジュール名を設定するので、命名規則に反していなければ何でも構いません。  
ここでは`filepath`から拡張子なしのファイル名(`a`)をモジュール名としています。

[code]

    from importlib.util import spec_from_file_location, module_from_spec
    import pathlib
    
    def 実行(filepath):
        module_name = pathlib.Path(filepath).stem.replace('-', '_')
        spec = spec_from_file_location(module_name, filepath)
        foo = module_from_spec(spec)
        spec.loader.exec_module(foo)
    
    実行(r"C:\tem\a.py")
    
[/code]

**参考資料**

  * [Python Tips: .py 拡張子の無い Python ファイルを import したい](https://www.lifewithpython.com/2022/09/python-import-module-without-py-extension.html)
  * [How do I import a module given the full path?](https://stackoverflow.com/a/67692)


CC BY-SA 4.0
2022-10-27T10:10:20.873
91864
2022-10-27T10:10:20.873
9820
91860
answer