試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Pythonのimport文について

(2014/12/30)リンク先を修正し、サンプルコードの内容もPython 3に対応した。また、幾つかの内容を追加している。

  1. import文とモジュール/パッケージ
  2. 探索パス
  3. import文のバリエーション
    1. 基本的な形
    2. モジュール名をたどらないで使用する
    3. 別名で使用
  4. Pythonの動作に関するimport文
  5. 簡単な例

import文とモジュール/パッケージ

import文では、指定した名前のPythonスクリプトやモジュール/パッケージを調べて、存在しない場合には例外(ImportError)を出し、存在する場合にはそのコードを実行する(中の変数や関数が読み込まれて利用可能となる)。
モジュールはディレクトリ構造により階層を持つことができ、import文で指定した階層以下が読み込まれる。このように階層から成るモジュールの集まりはパッケージと呼ばれ、モジュールの階層は「.」により区切られる。

探索パス

モジュールの探索パスは、起動時(Pythonの外)には環境変数PYTHONPATH・実行中(Pythonの中)にはsys.path*1で読み書きできる。
(2009/3/25)append()ではなく「sys.path.insert(0, '[ディレクトリ]')」で0番へのinsert()を行うと最も優先される。

import文のバリエーション

基本的な形

import sys

では「sys」モジュール以下の全ての変数や関数が「sys.」を先頭に付ける形で利用できるようになる。

import sys
print (sys.argv)

標準で用意されていないモジュールを使用する場合、import文が失敗する(例外が発生する)可能性があるため、try節にimport文を書いてexcept節にエラー出力や終了の処理を記述する。

import sys
try:
  import alsaaudio
except:
  sys.exit ('Error: pyalsaaudio not installed')

(2014/12/30)モジュール名はコンマ区切りにして同時に複数記述できる。

import sys, os

モジュール名をたどらないで使用する
xml.parsers.expat」のように複数の階層になっているもの(サブモジュール)を上の形のimport文で使用すると、中の関数などの名前をたどる際に長くなるが

from [モジュール名] import [使用したい変数や関数]

の形で書くことで、モジュール名の部分を飛ばして使用することができる。例えば

import xml.parsers.expat
p = xml.parsers.expat.ParserCreate ()

from xml.parsers.expat import ParserCreate
p = ParserCreate ()

と書くことができる。この場合の「import」の後ろの部分には「全て」を示す「*」も指定できる*2。モジュールの集まりであるパッケージにおける「*」の指定についてはチュートリアルも参照。
ただし、「sys」「os」などでこの形の指定をした場合、必ずしもPythonのコードが読みやすくなるとは言えず*3、「os」に至っては「*」指定をすると組み込み関数open()がos.open()で隠蔽されるという問題もあるため、避けたほうがよい。

別名で使用
上の「from xxx import xxx」の書き方を使用すると、モジュール側の変数や関数の名前をそのまま利用できるが、後ろに「as [名前]」を付けることで、別の名前で使用することができる。
下の例では関数gettext.gettext()_()として使用できるようにしている。

from gettext import gettext as _

(2014/12/30)この例の場合はgettext.install()を用いるのが便利。

Pythonの動作に関するimport文

(2014/12/30)「from __future__ import [機能を示す文字列]」の形のimport文を実行することで、Python構文解析の動作を(新しいものに)変えることのできる場合がある。例えば、バージョン2.6以上のPython 2で

from __future__ import print_function

を実行すると、Python 3と同様のprint()関数が利用できるようになる(Python 3で実行しても特にエラーになったりはしない)。代わりにprint文は使えなくなる。

簡単な例

下の2つのコードを同じディレクトリに配置するか、1つ目のコードを環境変数PYTHONPATHのディレクトリに配置してから2つ目のコードを実行する。
ファイル名: ${PYTHONPATH}/foo.py

AAA = 12345
def func (a):
  return a
def func2 (a, b):
  return '{0} and {1}'.format (a, b)
if __name__ != '__main__':
  print ('** imported foo.py **')

[任意]ファイル名: importtest.py

#! /usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

# foo.pyやモジュールfooの中の関数や変数に「foo.」付きでアクセス
print ('import foo')
import foo
print ('foo.AAA: {0}'.format (foo.AAA))
print ('foo.func("test"): {0}'.format (foo.func ('test')))
# 「foo.」なしではアクセスできないのを実験
try:
  print ('AAA: {0}'.format (AAA))
except NameError as e:
  print ('NameError({0})'.format (e))
try:
  print ('func2("You", "I"): {0}\n'.format (func2 ('You', 'I')))
except NameError as e:
  print ('NameError({0})\n'.format (e))

# funcとfunc2だけを「foo.」なしで使用する
print ('from foo import func, func2')
from foo import func, func2
print ('func("TEST"): {0}'.format (func ('TEST')))
print ('func2("drag", "drop"): {0}\n'.format (func2 ('drag', 'drop')))

# foo以下の全てを「foo.」なしで使用する
print ('from foo import *')
from foo import *
print ('AAA: {0}\n'.format (AAA))

# 別名(BBB)でAAAを使用
print ('from foo import AAA as BBB')
from foo import AAA as BBB
print ('BBB: {0}'.format (BBB))

下は実行結果。

import foo
** imported foo.py **
foo.AAA: 12345
foo.func("test"): test
NameError(name 'AAA' is not defined)
NameError(name 'func2' is not defined)

from foo import func, func2
func("TEST"): TEST
func2("drag", "drop"): drag and drop

from foo import *
AAA: 12345

from foo import AAA as BBB
BBB: 12345

「** imported foo.py **」は最初の1回しか出ていないが、今回の例では同じファイルが繰り返しimportされているためで、「from」を使用したimport文でも、コード中で初回のimportであれば出力される。下はPythonのシェルでのテスト。

$ PYTHONPATH=${PYTHONPATH}:[foo.pyのあるディレクトリ] python
(中略)
>>> from foo import func
** imported foo.py **
>>> 

また、foo.pyで__name__の値によって処理を分岐しているが、直接foo.pyを実行した場合にはこの値が「__main__」となり、importにより実行されたときにはその名前となる。上のfoo.pyの最後に

  print "__name__: " + __name__

を追加すると、出力は

import foo
** imported foo.py **
__name__: foo
foo.AAA: 12345
(以下略)

のようになる。

参考URL:

*1:「import sys」が必要で、追加はsys.path.append([ディレクトリ])で行う

*2:そのモジュールの中の全ての名前がモジュール名無しで使えるようになる

*3:モジュール名をたどる書き方のほうが分かりやすい場合も多い・スクリプトの長さが短く、かつモジュール階層の深い「os.path」などの関数を多用しているような場合では役に立つ気もする