Pythonのモジュールとパッケージがわからない
pytestを試している途中、テスト用のモジュールをtests
フォルダに入れただけで
よくわからなくなったのでモジュールとパッケージについて調べる
公式を見ながらいくよ
チュートリアルから:6. Modules — Python 3.7.3 documentation
リファレンスから:5. The import system — Python 3.7.3 documentation
そもそもモジュールとかパッケージとかいうのはなんなのか
A module is a file containing Python definitions and statements.
モジュールはPythonの定義や文を書いたファイル
Packages are a way of structuring Python’s module namespace by using “dotted module names”.
パッケージはドットを使ってモジュールの名前空間を構成するもの
A regular package is typically implemented as a directory containing an __init__.py file.
通常のパッケージは__init__.py
が含まれたディレクトリのこと
__init__.py
とは何か
The __init__.py files are required to make Python treat directories containing the file as packages.
パッケージであることを示す目印
In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.
空っぽでもいいし、初期化のコードを書いてもいい
これくらいで
まずは普通に上位のフォルダから下位のフォルダを参照する場合からやってみる
+- pymod/
+- mainmod.py
+- sub1
+- __init__.py
+- submod1.py
mainmod.py
はこうして
import sub1.submod1-1
print(sub1.submod1.submod1_func())
submod1-1.py
をこうした
__init__.py
はからっぽ
$ python mainmod1.py
submod1_func
できた
__init__.py
(と__init__.pyc
)を消してやってみる
$ python mainmod1.py
Traceback (most recent call last):
File "mainmod1.py", line 1, in <module>
import sub1.submod1_1
ImportError: No module named sub1.submod1_1
パッケージとして認識されなくなった
想定通り
mainmod1.py
をこう書き換えても大丈夫
from sub1 import submod1_1
print(submod1_1.submod1_1_func())
しかしsubmod1_1
とわざわざ指定するのは面倒
__init__.py
でsubmod1_1
の名前をまるごとimportしてやると
submod1_1
の指定を省略できる
import sub1
print(sub1.submod1_1_func())
flake8が
'from submod1_1 import *' used; unable to detect undefined names
とか
'submod1_1.*' imported but unused
とか言ってくるのはちょっと気になる
ほかに推奨の書き方があるのか
それともはじめから__init__.py
に書くものなのか
ためしに/opt/python3.7.3/lib/python3.7/unittest
の__init__.py
を
見てみると、*
ではないけどモジュールから名前をimportしてた
flake8をかけてみる
$ flake8 __init__.py
__init__.py:58:1: E402 module level import not at top of file
__init__.py:59:1: E402 module level import not at top of file
__init__.py:61:1: E402 module level import not at top of file
__init__.py:61:1: F401 '.suite.BaseTestSuite' imported but unused
__init__.py:62:1: E402 module level import not at top of file
__init__.py:62:1: F401 '.loader.makeSuite' imported but unused
__init__.py:62:1: F401 '.loader.getTestCaseNames' imported but unused
__init__.py:62:1: F401 '.loader.findTestCases' imported but unused
__init__.py:62:80: E501 line too long (80 > 79 characters)
__init__.py:64:1: E402 module level import not at top of file
__init__.py:64:1: F401 '.main.TestProgram' imported but unused
__init__.py:65:1: E402 module level import not at top of file
__init__.py:66:1: E402 module level import not at top of file
__init__.py:66:80: E501 line too long (80 > 79 characters)
__init__.py:74:1: E302 expected 2 blank lines, found 1
unusedも出てるし気にしなくていいのかな
でも気になる
かといってまるごと無視もしたくないし
次いく
兄弟フォルダを参照する場合
When packages are structured into subpackages (as with the sound package in the example), you can use absolute imports to refer to submodules of siblings packages.
パッケージがサブパッケージの形になってれば兄弟パッケージは「絶対import」ができる
sub2
フォルダを作ってsubmod2_1.py
を入れる
こう書けるってことだろうか
import pymod.sub1
print(pymod.sub1.submod1_1_func())
$ python submod2_1.py
Traceback (most recent call last):
File "submod2_1.py", line 1, in <module>
import pymod.sub1
ImportError: No module named pymod.sub1
pymod
フォルダに__init__.py
がないから?
いや作ってみたけどダメ
sub2
フォルダにも作ってみたけどダメ
import pymod.sub1
をfrom pymod import sub1
とか
from pymod.sub1 import submod1_1
とかに変えてみてもダメ
子フォルダで実行してるのがだめかと思って
mainmod1_1.py
にimport sub2.submod2_1
を追加して
pymod
フォルダで実行してもやっぱりpymod
なんて知らないと言う
そもそも今いるフォルダがpymod
パッケージだと思ってないのかな?
相対パスのところだけどこう書いてあるのが気になる
Since the name of the main module is always "main", modules intended for use as the main module of a Python application must always use absolute imports.
メインモジュールの名前はいつも"main"なので、Pythonアプリケーションのメインモジュールは必ず絶対インポートを使え
pymod
じゃなくて__main__
と思ってるのかなあ
python submod2_1.py
で実行したときはsubmod2_1.py
がメインモジュールって
ことになってうまくいかない、という話はありそうだけど
じゃあどう書けばいいの
なにか勘違いしている気がするけどわからない
明日もう一度ちゃんと読んでみよう