web-dev-qa-db-ja.com

「モジュールのインポート」または「モジュールのインポートから」を使用しますか?

import moduleまたはfrom module importを使用するのが最善かどうかについて包括的なガイドを見つけようとしましたか? Pythonで始めたばかりで、ベストプラクティスを念頭に置いて始めようとしています。

基本的に、誰かが彼らの経験を共有できるか、他の開発者がどんな好みを持っているか、そして今後のgotchasを避けるための最良の方法は何かを望んでいたのですか?

328

import modulefrom module import fooの違いは主に主観的です。一番好きなものを選び、それを一貫して使用してください。ここに、決定に役立ついくつかのポイントがあります。

import module

  • 長所:
    • importステートメントのメンテナンスの削減。モジュールの別のアイテムの使用を開始するために追加のインポートを追加する必要はありません
  • 短所:
    • コードにmodule.fooを入力するのは面倒で冗長な場合があります(import module as moを使用してからmo.fooと入力することで、tediumを最小限に抑えることができます)

from module import foo

  • 長所:
    • fooを使用するための入力が少ない
    • モジュールのどのアイテムにアクセスできるかをさらに制御する
  • 短所:
    • モジュールの新しいアイテムを使用するには、importステートメントを更新する必要があります
    • fooに関するコンテキストが失われます。たとえば、ceil()math.ceil()に比べて何をするのかは明確ではありません

どちらの方法でもかまいませんが、do n't use from module import *

妥当な大規模なコードセットの場合、import *を使用すると、モジュールにセメントで固定され、削除できなくなります。これは、コードで使用されているアイテムが「モジュール」からのものであるかどうかを判断するのが難しく、これ以上importを使用しないと思うポイントに到達するのは簡単ですが、確認するのは非常に難しいからです。

396
Mark Roddy

ここには、モジュールへの書き込みに関連する、言及されていない別の詳細があります。確かにこれはあまり一般的ではないかもしれませんが、時々必要になりました。

Pythonでの参照と名前バインディングの動作方法により、モジュール内のシンボル(foo.barなど)をそのモジュールの外部から更新し、他のインポートコードにその変更を「参照」させる場合は、fooをインポートする必要があります特定の方法。例えば:

モジュールfoo:

bar = "apples"

モジュールa:

import foo
foo.bar = "oranges"   # update bar inside foo module object

モジュールb:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

ただし、モジュール名ではなくシンボル名をインポートする場合、これは機能しません。

たとえば、モジュールaでこれを行う場合:

from foo import bar
bar = "oranges"

Barの私の設定は、モジュールa内の名前「bar」に影響するだけで、fooモジュールオブジェクトに「到達」せず、その「bar」を更新しなかったため、aの外側のコードはbarを「オレンジ」と見なしません。

108

importimport fromについてはすでに多くの人が説明していますが、ボンネットの下で何が起こるのか、それが変化するすべての場所についてはもう少し説明したいと思います。


import foo

fooをインポートし、現在のネームスペースにそのモジュールへの参照を作成します。次に、完成したモジュールパスを定義して、モジュール内から特定の属性またはメソッドにアクセスする必要があります。

例えば。 foo.barbarではない

from foo import bar

fooをインポートし、リストされたすべてのメンバー(bar)への参照を作成します。変数fooを設定しません。

例えば。 barは、bazまたはfoo.bazではありません

from foo import *

fooをインポートし、現在のネームスペースでそのモジュールによって定義されているすべてのパブリックオブジェクトへの参照を作成します(__all__が存在する場合は__all__にリストされているもの、そうでない場合は_で始まらないものすべて)。変数fooを設定しません。

例えば。 barおよびbazが、_quxまたはfoo._quxではありません。


では、import X.Yを実行するタイミングを見てみましょう。

>>> import sys
>>> import os.path

osおよびsys.modulesという名前のos.pathを確認します。

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

osおよびos.pathを使用して、globals()およびlocals()名前空間の辞書を確認します。

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

上記の例から、osのみがローカルおよびグローバル名前空間に挿入されることがわかりました。そのため、次を使用できるはずです。

 >>> os
 <module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

しかし、pathではありません。

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Locals()名前空間からosを削除すると、sys.modulesに存在していても、osおよびos.pathにアクセスできなくなります。

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

では、import fromについて説明しましょう。

from

>>> import sys
>>> from os import path

osおよびsys.modulesos.pathを確認します。

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

sys.modulesで、import nameを使用して以前と同じように見つけたことがわかりました

OK、locals()およびglobals()名前空間の辞書でどのように見えるかを確認しましょう:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

os.pathではなく、名前pathを使用してアクセスできます。

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

locals()から「パス」を削除しましょう:

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

エイリアスを使用した最後の例:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

そして、パスが定義されていません:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
57
James Sapam

どちらの方法もサポートされています。理由は次のとおりです。一方が他方より適切な場合があります。

  • import module:モジュールの多くのビットを使用しているときはいいですね。欠点は、各参照をモジュール名で修飾する必要があることです。

  • from module import ...:インポートされたアイテムは、モジュール名のプレフィックスなしで直接使用できます。欠点は、使用するものをそれぞれリストする必要があり、コードのどこから何かが明らかになっていないことです。

どちらを使用するかは、コードを明確で読みやすいものにするかどうかに依存し、個人的な好みとは少し関係があります。コードでは、オブジェクトや関数がどこから来たのかが非常に明確であるため、一般的にimport moduleに傾いています。コードでオブジェクト/関数a lotを使用している場合は、from module import ...を使用します。

38
dwc

私は個人的に常に使用しています

from package.subpackage.subsubpackage import module

そして、すべてにアクセスします

module.function
module.modulevar

理由は、同時に短い呼び出しがあり、各ルーチンのモジュール名前空間を明確に定義するためです。これは、ソースで特定のモジュールの使用を検索する必要がある場合に非常に便利です。

言うまでもなく、import *は使用しないでください。名前空間を汚染し、特定の関数がどこから来たか(どのモジュールから)を教えてくれないためです。

もちろん、次のように、2つの異なるパッケージの2つの異なるモジュールに同じモジュール名がある場合、トラブルで実行できます。

from package1.subpackage import module
from package2.subpackage import module

この場合、もちろんトラブルに直面しますが、パッケージレイアウトに欠陥があるという強力なヒントがあり、それを再考する必要があります。

32
Stefano Borini
import module

モジュールの多くの関数を使用する場合に最適です。

from module import function

functionのみが必要な場合に、モジュールのすべての関数と型でグローバル名前空間を汚染しないようにする場合に最適です。

14
Andrew Hare

言及されていない別の違いを次に示します。これは http://docs.python.org/2/tutorial/modules.html からそのままコピーされます

使用する場合は注意してください

from package import item

アイテムは、パッケージのサブモジュール(またはサブパッケージ)でも、関数、クラス、変数など、パッケージで定義された他の名前でもかまいません。 importステートメントは、最初にアイテムがパッケージで定義されているかどうかをテストします。そうでない場合、それはモジュールであると想定し、それをロードしようとします。見つからない場合、ImportError例外が発生します。

逆に、次のような構文を使用する場合

import item.subitem.subsubitem

最後のアイテムを除く各アイテムはパッケージでなければなりません。最後のアイテムはモジュールまたはパッケージにすることができますが、前のアイテムで定義されたクラス、関数、または変数にすることはできません。

7
user2141737

これら2つの方法のもう1つの微妙な違いを発見しました。

モジュールfooが次のインポートを使用する場合:

from itertools import count

次に、モジュールbarは、countではなくfooで定義されているかのように、誤ってitertoolsを使用できます。

import foo
foo.count()

fooが使用する場合:

import itertools

間違いはまだ可能ですが、起こりそうにありません。 barの必要性:

import foo
foo.itertools.count()

これは私にいくつかのトラブルを引き起こしました。誤って、それを定義していないモジュールから例外をインポートし、他のモジュールからのみインポートしたモジュールがありました(from module import SomeExceptionを使用)。インポートが不要になって削除されたときに、問題のモジュールが壊れていました。

6
Jan Wrobel

私も初心者なので、これを簡単な方法で説明しようとしています。Pythonには、次の3つのタイプのimportステートメントがあります。

1。一般的なインポート:

import math

このタイプのインポートは私の個人的なお気に入りですが、このインポート手法の唯一の欠点は、モジュールの機能を使用する必要がある場合、次の構文を使用する必要があることです:

math.sqrt(4)

もちろん、タイピングの労力が増えますが、初心者として、それに関連するモジュールと機能を追跡するのに役立ちます(優れたテキストエディターはタイピングの労力を大幅に削減し、推奨されます) 。

このimportステートメントを使用すると、入力の労力をさらに減らすことができます:

import math as m

今、math.sqrt()を使用する代わりに、m.sqrt()を使用できます。

2。関数のインポート:

from math import sqrt

このタイプのインポートは、コードがモジュールの単一または少数の関数にアクセスするだけの場合に最適ですが、モジュールの新しいアイテムを使用するにはimportステートメントを更新する必要があります。

3。ユニバーサルインポート:

from math import * 

タイピングの労力を大幅に削減しますが、モジュールのさまざまな関数でコードを埋め、その名前がユーザー定義関数の名前と競合する可能性があるため、お勧めしません。example:

独自の名前付きsqrtの関数があり、数学をインポートする場合、関数は安全です。sqrtがあり、math.sqrtがあります。ただし、math import *から実行すると、問題が発生します。つまり、まったく同じ名前の2つの異なる関数です。ソース: Codecademy

4
Shashank Rawat

from x import *について人々が言っ​​たことに加えて、名前がどこから来たかを見分けるのをより難しくすることに加えて、これはPylintのようなコードチェッカーをスローします。これらの名前は未定義の変数として報告されます。

4
DNS

これに対する私自身の答えは、まず、使用するモジュールの数に依存します。 1つまたは2つだけを使用する場合、多くの場合、from ... importを使用します。これにより、ファイルの残りの部分でのキーストロークが少なくなりますが、多くの異なるモジュールを使用する場合、importを選択します。これは、各モジュール参照が自己文書化されることを意味するためです。探し回る必要なく、各シンボルの由来を確認できます。

通常、自己文書化スタイルのプレーンインポートを好み、インポートするモジュールが1つしかない場合でも、モジュール名を入力しなければならない回数が10から20を超えると、インポートのみに変更します。

驚くほど誰も話していないことがわかった重要な違いの1つは、プレーンimportを使用してprivate variableとインポートされたモジュールからのprivate functionsは、from-importステートメントでは不可能です。

enter image description here

画像内のコード:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work
1
Saurav Sahu

これに追加したいのですが、インポート呼び出し中に考慮すべきことがあります:

私は次の構造を持っています:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.disは違いを示します。

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

最終的には同じように見えます(各例でSTORE_NAMEが結果になります)が、次の4つの循環インポートを考慮する必要がある場合は注意が必要です。

例1

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

これは動作します

例2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

サイコロなし

例3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

同様の問題...しかし、明らかにx import yはyとimport import x.yと同じではありません

例4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

これも動作します

0
ahfx

モジュールのインポート-モジュールから別のものを取得するための追加の作業は必要ありません。冗長な型付けなどの欠点があります

モジュールのインポート元-モジュールのどの項目にアクセスできるかをより少ない入力と詳細制御。モジュールから新しい項目を使用するには、インポート文を更新する必要があります。

0
Dlucidone