Pythonの相対的インポートと絶対的インポート

簡単なプロジェクトは1つのファイルにまとめることができますが、ほとんどのPython開発プロジェクトは、管理しやすいように複数のファイルが必要になります。

つまり、あるファイルを別のファイルにインポートする方法が必要なのです。

しかし、多くのPythonistはファイルのインポートが分かりにくいと感じています。

幸い、様々なPythonのimport文の違いを知っていれば、簡単です。

インポートとは?

インポートとは、PythonファイルやPythonモジュールが他のPythonファイルやモジュールからスクリプトにアクセスできるようにすることを指します。

自分のプログラムがアクセスできる関数やプロパティしか使うことができません。

例えば、数学的な機能性を使いたい場合は、まずmathパッケージをインポートする必要があります。

これは、使いたいものをすべてPythonで定義してからでないと使えないからです。

例えば、次のようなコードを書くと、PythonはNameErrorを出します。

myPi = math.pi


これは、 math オブジェクトもそのプロパティやメソッドも、言語自体がネイティブに利用できないからです。

math` オブジェクトを使用するには、最初にそれをインポートする必要があります。

import math


myPi = math.pi
print myPi


インポート`ステートメントは、プログラムのカレントスコープにオブジェクトを追加します。

輸入のしくみ

ファイルやモジュールをインポートするために、import文はいろいろなことをします。

まず、Pythonが以前にインポートしたコードを保存している sys.modules で、あなたのモジュールやパッケージを探します。

もしPythonがそこでモジュールを見つけられなかったら、次にPython Standard Libraryからモジュールを探します。

それでもモジュールが見つからない場合は、カレントディレクトリと system.path にリストアップされているものから始めて、ストレージスペース全体を調べます。

もし、これらの場所でモジュールが見つかれば、プログラムにモジュールを追加し、そうでなければ、 ModuleNotFoundError を出します。

インポート文の構文

モジュールを直接インポートするには、importキーワードの後にモジュール名やパッケージ名を記述するだけです。

この文は大文字と小文字を区別することに注意してください。

import mymodule


しかし、Pythonはコードをインポートするために、より洗練された構文を提供しています。

この2番目の形式は、 from キーワードも含みます。

from mypackage import mymodule


このフォーマットでは、必要なモジュールやコードがどこにあるのかを指定します。

コード、モジュール、サブパッケージの名前を mymodule に、その場所を mypackage に指定します。

このようなimport文は、パッケージそのものではなく、指定したパッケージのコードの一部だけをimportしたい場合に最適です。

as` キーワードを含めることで、モジュールの名前を変更することもできます。

import mymodule as oMyFunction


アスタリスク (*) をワイルドカードとして使用することもできます。

次の文は math パッケージに含まれるすべての関数とプロパティをインポートします。

from math import *


構文に関係なく、常に推奨されるインポートのベストプラクティスに従う必要があります。

アブソリュートインポート

絶対インポートには、プログラムのルートフォルダから始まるスクリプトへの全パスが含まれます。

各フォルダーをピリオドで区切る必要がありますが、必要な長さだけピリオドを持たせることができます。

以下は、絶対インポートの例です。

from package1.firstmodule import firstmodule
import package1.secondmodule.myfunction


絶対輸入のメリット・デメリット

他の言語とは異なり、ほとんどのPython開発者は相対インポートよりも絶対インポートを好んで使用します。

これは、絶対インポートを使うと、何をしようとしているのかが本当に明確になるからです。

ファイルの実際の位置は、コードのすぐそこにあります。

実際、あなたはコードのどこででもそれらを使用することができます。

そのまま動作します。

しかし、絶対的なインポートはかなり長くなる可能性があります。

プロジェクトにサブパッケージ、サブパッケージ、サブパッケージがある場合、import文は1行のコードを超えて拡張される可能性があります。

そのような場合は、相対インポートを使用したほうがよいでしょう。

また、異なる起動ファイルを使用してプログラムを起動したときに、問題を発見することがあります。

Pythonインタプリタは起動ファイルのカレントフォルダを sys.path パッケージルートとして宣言するだけです。

これは、ルートフォルダにあるファイルだけを使ってプログラムを読み込むのであれば問題ありません。

なぜなら、sys.pathはスクリプトの間中、静的なままだからです。

しかし、サブフォルダからプログラムを起動したり、sys.pathが変更されるような状況では状況が変わってきます。

その場合、あなたの「ルートフォルダ」はサブフォルダになります。

暗黙のインポートが使えないので(後述します)、サブフォルダ外のファイルはプログラムからアクセスできなくなります。

これに対しては、2つの回避策があります。

サブフォルダースクリプトをインポートモジュールとして開始するか、コード内に直接 sys.path を追加するかです。

例えば、以下のようになります。

  • 実行時にモジュールをインポートする: python -m packA.a2.
  • ファイルをインポートする前に、sys.path を追加してください。
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from packA.subA import sa2


相対的輸入額

相対インポートでは、リソースが現在のコードファイルに対して相対的に存在する場所のみを指定します。

これは暗黙的または明示的に行うことができますが、暗黙的な相対インポートはPython 3で削除されました。

構文としては、相対インポートはドット表記を使用します。

1つのドットは現在のスクリプトのディレクトリを表し、2つのドットは親フォルダを表します。

2つのドットは親フォルダを表します。

3つ目のドットは祖父母を意味し、以下同様です。

UNIX系のOSやWindowsのコンソールを使っている人なら、この方式に慣れているかもしれません。

以下は、相対インポートの例です。

  • 明示的インポート
import other
from . import some_class
from .subA import sa1


  • 暗黙のインポート
from .some_module import some_class
import some_function
import subA.sa1


相対輸入とそのメリット・デメリットについて

相対インポートは、絶対インポートほど長くなることはありません。

相対インポートの場合、絶対インポートのように長くなることはほとんどなく、とんでもなく長い絶対文も、次のような簡単なものに変えることができます。

from ..my_sub_package.my_module import my_function


しかし、モジュールへのパスも隠されてしまいます。

あなたが唯一の開発者であれば問題ないかもしれませんが、実際のディレクトリ構造が変わる可能性のある開発チームの一員である場合は厄介なことになります。

どのインポートを使うか?

サブパッケージが何層にも重なっているような大きなプロジェクトでない限り、常に絶対的なインポートを使用するべきです。

そうすれば、あなたのコードは誰が見ても簡単に理解できるようになります。

たとえ長いパスがあったとしても、コードと生活をシンプルにするために、絶対的なステートメントだけを使用するようにプログラムを書くようにすべきです。

結論

他の近代的なプログラミング言語と同様に、Pythonでは他のファイルやモジュールからコードをインポートすることができます。

しかし、importシステムの背後にある概念を理解しない限り、これは混乱し、エラーが発生しやすいプロセスに変わる可能性があります。

この記事では、絶対インポートと相対インポートを含む、Pythonプログラムにコードをインポートするさまざまな方法について調べました。

また、それぞれの長所と短所を比較し、異なるユースケースでそれぞれの長所を持つようにしました。

タイトルとURLをコピーしました