LoginSignup
85
66

More than 3 years have passed since last update.

pythonで上のディレクトリ内ファイルをimportする方法

Last updated at Posted at 2019-05-19

はじめに

普段はC++を使っているのですが,Pythonで何気なくプログラミングをしていて,ソースコードが長くなることを避けるために関数のファイルを分割してimportをしようと思いました.

同じことで困る人もいると思ったので,素早く解決できることを願います.短気な方はこちらへジャンプしてください.

他のコードからもimportすることを見越して,

$ tree
.
├── dir1
│   ├── mod1.py
│   ├── mod2.py
│   └── mod3.py
└── dir2
    └── main.py

のようなフォルダ構造でやろうと思っていました.
また,書くときに面倒にならないように,dir1.mod1.func1()
のようではなく,func1()と関数を使用できるようにしたかった.

問題

main.py
from ..dir1 import mod1

print('import was completed!')

のようにすると,

error
$ python main.py 
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from ..dir1 import mod1
ValueError: attempted relative import beyond top-level package

と怒られてしまった.ディレクトリに入れてないのかなと思い,mod1.pyを一つ上の階層に移して

main.py
from .. import mod1

print('import was complated!')

と変更した結果,

error
$ python main.py 
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from .. import mod1
ValueError: attempted relative import beyond top-level package

また怒られた.

解決方法

調べてみると,

 実行ディレクトリをルートとする

という仕様があるらしく,上のディレクトリにいけないらしい.
そこで,

main.py
import sys
sys.path.append('../')
from dir1.mod1 import *

if __name__ == '__main__':
    importTest()
dir1/mod1.py
def importTest():
    print('import was completed!')

と変更して実行すると,

run_main
$ python main.py 
import was completed!

できた.

改善

このままでは,dir1/内のmod1.py,mod2.py,mod3.py全てをimport`する場合,3行要してしまうのは嬉しくなく,

folder
$ tree
.
├── dir1
│   ├── __init__.py
│   ├── mod1.py
│   ├── mod2.py
│   └── mod3.py
└── dir2
    └── main.py

のようにした.各ファイルの中身は以下のようにした.この書き方をすることで,関数をそのまま使うことができた.

main.py
import sys
sys.path.append('../')
from dir1 import *

if __name__ == '__main__':
    importTest1()
    importTest2()
    importTest3()
__init__.py
from .mod1 import *
from .mod2 import *
from .mod3 import *
mod1.py
def importTest1():
    print('mod1 import was complated!')
mod2.py
def importTest2():
    print('mod2 import was complated!')
mod3.py
def importTest3():
    print('mod3 import was complated!')

この実行結果は

result
$ python main.py 
mod1 import was complated!
mod2 import was complated!
mod3 import was complated!

これで当初の目的が果たされた.

Gitで使う際

以上のものを使用する際には__pycache__が邪魔だったため,.gitignoreへ以下を追記.

.gitignore
*__pycache__/

参考

おわりに

一応希望通りの動きは果たせたのですが,応急処置感が否めないので,もっといいやり方があったら教えていただけると幸いです.

85
66
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
85
66