Python3でのmodule import

2022.12.08
はじめに
Python3でのimport文, fromや__init__.pyなどに若干の苦手意識があったため整理しました。
用語
- module 1つの機能単位. 1ファイルに相当.
- package moduleの集まり. 1ディレクトリに相当.
基本的な使い方
ファイル構成
自作モジュール, パッケージをimportする状況を考えます.
ファイル構成は以下の通り
$ tree -L 2
.
├── pkg
│ └── hola.py
├── hello.py
└── main.pyimport module名
最も基本的なimport方法で, module名の後にasで別名をつけることができます。自作の場合はmodule名はファイル名と同じで, 普通importできるのは同じディレクトリ内のmoduleのみ。import <package名>.<module名>となる場合もあります。
例
HELLO="hello!"import hello
print(hello.HELLO)hello!from <X> import <Y>
| X | Y |
|---|---|
| package名 | module名 |
| module名 | 識別子 |
などのパターンがあります。
例
HOLA="hola!"from pkg import hola
print(hola.HOLA)他にも
import pkg.hola
print(pkg.hola.HOLA)や
from pkg.hola import HOLA
print(HOLA)とも書けます
任意のディレクトリにあるmoduleをimport
次は別のディレクトリ構成にしてみます
$ tree -L 2
.
├── pkg1
│ ├── hola.py
│ └── __init__.py
└── pkg2
└── main.pyimport sys
import os
sys.path.append(os.path.abspath('path/to/src'))
import hola
print(hola.HOLA)sys.pathはimportするmoduleへのパスのリストです。別のディレクトリからmoduleをimportする場合はこのlistにpathをマニュアルで加えます。
結局__init__.pyはなんのためにあるのか
__init__.pyとは
__init__.pyというのはpackageが読み込まれる際の一番初めに実行されるファイルです。packageを作る際に必要ですが, ややこしいのはPython3.3の名前空間パッケージという機能追加のせいで__init__.pyがなくてもパッケージとして利用できるようになった点です。
名前空間パッケージは同じ名前のディレクトリが別のpathに存在する際にひとつのパッケージにまとめるといった特殊な用途で使うもので, 通常は__init__.pyを置いた方がよいです。
__init__.pyの利用例
空のファイルを置くだけだと存在意義がよく分からなくなりそうなので実際に__init__.pyを使う例として, 環境変数ENVがdevelopmentかproductionかでmoduleを分けるような場合を考えてみます。
$ tree -L 2
.
├── pkg1
│ ├── __init__.py
│ ├── dev_logger.py
│ └── prod_logger.py
└── pkg2
└── main.pyfrom dotenv import laod_dotenv
import os
if os.environ.get("ENV")=="production":
from . import prod_logger as logger
else:
from . import dev_logger as logger このようにするとmainからはpkg1のloggerを読み込むだけで環境変数に応じたmoduleを使うことができます。
他にも__all__という変数を定義することでfrom pkg import *としたときに読み込むmoduleを設定するのによく使われているようです。