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


411

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

基本的に、私は誰かが彼らの経験を共有できるか、他の開発者がどのような好みを持っているか、そして将来の問題を避けるための最良の方法は何かを望んでいましたか?


5
選択した答えが間違っていることをお知らせします。それは違いがあるのに対し、違いは主観的であると述べています。これにより、バグの検出が困難になる可能性があります。Michael Ray Lovettsの回答を参照してください。
Mayou36


2
特定の名前付き識別子を輸入差の地獄あります'from module import X,Y,ZVsが'from module import *。後者は名前空間を汚染し、モジュールで何が起こっているかによって予測できない結果をもたらす可能性があります。さらに悪いことにfrom module import *、複数のモジュールを使用しています。
smci 2018

回答:


474

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

import module

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

from module import foo

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

どちらの方法でもかまいません、は使用しないでくださいfrom module import *

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


66
+1は「from module import *」の使用を妨げるため、名前空間が乱雑になるだけです。
クリスチャンウィッツ

22
名前空間を乱雑にすることは、 "import *"の最も問題の多い部分ではありません。読みやすさの低下です。名前の競合は、(ユニット)テストで明らかになります。しかし、インポートされたモジュールから使用するすべての名前は完全なものではなく、それらが由来するヒントはほとんどありません。「輸入*」は絶対嫌いです。
ユルゲンA.エアハルト

21
PythonのZenは、明示的が暗黙的よりも優れていると言っていませんか?
アントニーコッホ

8
from module import *次のように使用すると、特に役立ちますif(windows):\n\t from module_win import * \n else: \n\t from module_lin import *。次に、module_linとmodule_winの関数名が同じ名前である場合、親モジュールにOSに依存しない関数名が含まれる可能性があります。どちらかのクラスを条件付きで継承するようなものです。
anishsane 2013年

19
@anishsane。それを行う別の方法があります。module_winを何かとしてインポートします。次に、常にsomething.method_name()を使用します
Vinay

163

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

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

モジュール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"

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


最後の例では、「foo.bar = "orange"」を呼び出して「foo」内の「bar」を更新できますか?
velocirabbit

4
いいえ、最後の例では、名前「foo」は不明です
Ghislain Leveque

31
この回答は、質問に対する「真の」回答を提供します。2つのインポートバリアントの違いは何
ですか

3
この答えが完全に正しいことを証明するためにスニペットを書きましたが、この背後にある理論的根拠は何ですか?
huangbeidu

私はあなたが言っていることはローカル変数を持つためにシンボル名をインポートするがグローバル変数を持つためにモジュール名をインポートすることだと思いますか?
WinEunuuchs2Unix 2018

79

多くの人がimportvs についてすでに説明しましたがimport from、私はフードの下で何が起こるか、そしてそれが変わるすべての場所がどこにあるかについてもう少し説明したいと思います。


import foo

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

たとえばfoo.barではなくbar

from foo import bar

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

例えばbarなく、bazまたはfoo.baz

from foo import *

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

たとえばbar、またはでbazはなく。_quxfoo._qux


では、いつ実行するか見てみましょうimport X.Y

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

sys.modules名前osとチェック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'>

確認globals()locals()名前空間のdictsとosos.path

 >>> 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
>>>

あなたが削除するとos地元の人々から()名前空間を、あなたがアクセスすることはできませんosとしてだけでなくos.path、彼らはsys.modulesに存在するにもかかわらず:

>>> 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

およびで確認sys.modulesしてください:osos.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'
>>>

あなたはではpathなく名前を使ってアクセスできますos.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'
>>>

8
これは冗長ですが、これはかなり複雑な質問に対するリストでの最良の回答です。この特定の問題について、スタイルよりも重要な「内部」の微妙な点を説明するのに役立つ実際のコードを提供します。私はそれを複数回賛成できればいいのに!
マイクウィリアムソン

を使用as SYMBOLすると、この答えの動作がまったく変わりますか?
Maximilian Burszley

40

両方の方法が理由でサポートされています。一方が他方より適切である場合があります。

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

  • from module import ...:インポートされたアイテムがモジュール名の接頭辞なしで直接使用できるのは素晴らしいことです。欠点は、使用するものをすべてリストする必要があること、およびコードのどこから来たのかが明確でないことです。

どちらを使用するかは、コードが明確で読みやすくなるかどうかに依存し、個人の好みとはほとんど関係ありません。import moduleコードではオブジェクトや関数がどこから来たのか非常にはっきりしているので、私は一般的に傾いています。私が使用してfrom module import ...、私はいくつかのオブジェクトを使用していたときに/機能をたくさんのコードで。


1
from M import Xどうにかして修飾子を使用することの利点を引き続き使用する方法はありますか?M.Xインポート後もそれができれば、両方の長所を手に入れることができるようです。
節足動物、

@artgropod:ちょっと。できますclass m: from something.too.long import x, y, z。しかし、それは本当にお勧めしません。
リーライアン

35

個人的にはいつも使っています

from package.subpackage.subsubpackage import module

そしてすべてにアクセスする

module.function
module.modulevar

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

言うまでもなく、インポート*は使用しないでください。これは、ネームスペースを汚染し、特定の関数がどこから来たか(どのモジュールから)を通知しないためです。

もちろん、次のように、2つの異なるパッケージの2つの異なるモジュールに同じモジュール名を指定すると、問題が発生する可能性があります

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

この場合、もちろん問題が発生しますが、パッケージレイアウトに欠陥があるという強いヒントがあり、再考する必要があります。


10
最後のケースでは、いつでも使用できます。pkgN.sub.moduleをmodNとしてインポートし、各モジュールに異なる名前を付けます。また、 'import modulename as mod1'パターンを使用して、長い名前を短くしたり、単一の名前を変更して同じAPIの実装(DB APIモジュールなど)を切り替えたりすることもできます。
ジェフシャノン

15
import module

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

from module import function

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


7
確かに、 'import module'を実行した場合、グローバル名前空間で唯一のものは 'module'ですか?名前空間を汚染するのは、「from .. import *」を実行した場合のみです。
John Fouhy

10

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

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

from itertools import count

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

import foo
foo.count()

foo使用する場合:

import itertools

間違いはまだ起こり得ますが、犯される可能性は低くなります。barする必要がある:

import foo
foo.itertools.count()

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


10

ここでは言及されていない別の違いがあります。これはhttp://docs.python.org/2/tutorial/modules.htmlからそのままコピーされます

使用するときは注意してください

from package import item

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

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

import item.subitem.subsubitem

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


もう1つ気づいたのは、itemがパッケージ内のサブモジュールでもある場合、「from package import item」は機能しますが、「import package」package.item.subitem = ...は、パッケージの空のinit .py では機能しません。パッケージのinitファイルに「インポートアイテム」を持っています。
Amitoz Dandiana 2018

6

私も初心者なので、簡単に説明しようと思います。Pythonでは、次の3種類のimportステートメントがあります。

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

import math

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

math.sqrt(4)

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

次のインポート文を使用すると、入力の手間をさらに減らすことができます。

import math as m

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

2.関数のインポート:

from math import sqrt

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

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

from math import * 

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

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


5
import package
import module

ではimport、トークンは、モジュール(Pythonコマンドを含むファイル)またはパッケージである必要があります(フォルダsys.pathのファイルを含みます__init__.py。)

サブパッケージがある場合:

import package1.package2.package
import package1.package2.module

フォルダ(パッケージ)またはファイル(モジュール)の要件は同じですが、フォルダやファイルが内部でなければなりませんpackage2内部でなければならないpackage1、との両方package1package2含まれている必要があります__init__.pyファイルを。https://docs.python.org/2/tutorial/modules.html

fromインポートのスタイル:

from package1.package2 import package
from package1.package2 import module

パッケージまたはモジュールは、importステートメントを含むファイルの名前空間をの代わりにmodule(またはpackage)として入力しますpackage1.package2.module。いつでもより便利な名前にバインドできます。

a = big_package_name.subpackage.even_longer_subpackage_name.function

from特定の関数または変数に名前を付けることができるのは、インポートのスタイルのみです。

from package3.module import some_function

許可されていますが、

import package3.module.some_function 

許可されていません。


4

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


3

これに対する私自身の答えは、まず最初に、使用するさまざまなモジュールの数に大きく依存します。1つまたは2つだけを使用する場合は、ファイルの残りの部分でのキーストロークが少なくなるため、多くの場合from... importを使用しますが、多くの異なるモジュールを使用する場合は、importこれは、各モジュール参照が自己文書化されることを意味するためです。探し回らなくても、各シンボルの出所がわかります。

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


1

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

ここに画像の説明を入力してください

画像内のコード:

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

0

モジュールのインポート-モジュールから別のものをフェッチするために追加の作業は必要ありません。冗長なタイピングなどの欠点があります

モジュールのインポート元-入力の手間を軽減&アクセスできるモジュールのアイテムをより詳細に制御します。モジュールの新しいアイテムを使用するには、インポートステートメントを更新する必要があります。


0

ほとんどがベア関数(base64mathosshutilsystimeなど)を含む組み込みモジュールがいくつかあり、これらのベア関数を名前空間にバインドして、コード。名前空間なしでこれらの関数の意味を理解することがいかに難しいかを考えてみましょう。

copysign(foo, bar)
monotonic()
copystat(foo, bar)

それらがいくつかのモジュールにバインドされているときよりも:

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

異なるモジュール間の競合を回避するために名前空間が必要な場合もあります(json.loadpickle.loadの比較)。


一方、ほとんどのクラス(configparserdatetimetempfilezipfileなど)を含むいくつかのモジュールがあり、それらの多くはクラス名を十分に説明しています:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

そのため、コード内で追加のモジュール名前空間を使用してこれらのクラスを使用すると、新しい情報が追加されるのか、コードが長くなるのか、という議論があり得ます。


0

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

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

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 from yはimport import xyと同じではありません。

例4

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

これも動作します


0

これは私の現在のディレクトリの私のディレクトリ構造です:

.  
└─a  
   └─b  
     └─c
  1. import文は覚えているすべての中間の名前を
    これらの名前修飾する必要があります

    In[1]: import a.b.c
    
    In[2]: a
    Out[2]: <module 'a' (namespace)>
    
    In[3]: a.b
    Out[3]: <module 'a.b' (namespace)>
    
    In[4]: a.b.c
    Out[4]: <module 'a.b.c' (namespace)>
  2. from ... import ...文は覚えているだけで、インポートの名前を
    この名前修飾しないでください。

    In[1]: from a.b import c
    
    In[2]: a
    NameError: name 'a' is not defined
    
    In[2]: a.b
    NameError: name 'a' is not defined
    
    In[3]: a.b.c
    NameError: name 'a' is not defined
    
    In[4]: c
    Out[4]: <module 'a.b.c' (namespace)>

  • 注:もちろん、手順1と2の間にPythonコンソールを再起動しました。

0

Jan Wrobelが述べているように、さまざまな輸入の1つの側面は、輸入がどのように開示されているかです。

モジュールmymath

from math import gcd
...

mymathの使用:

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

gcd内部使用のみを目的としてインポートし、のユーザーに開示しない場合mymath、これは不便な場合があります。これはかなり頻繁にあり、ほとんどの場合、「モジュールをクリーンに保つ」必要があります。

Jan Wrobelimport math代わりにこれを使用してこれをさらに不明瞭にするという提案とは別に、主要なアンダースコアを使用してインポートを開示から隠し始めました。

# for instance...
from math import gcd as _gcd
# or...
import math as _math

大規模なプロジェクトでは、この「ベストプラクティス」により、後続のインポートに開示されるものとされないものを正確に制御できます。これにより、モジュールがクリーンに保たれ、特定のサイズのプロジェクトで見返りが得られます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.