web-dev-qa-db-ja.com

`from ... import`と` import .`

コードの断片に違いがあるかどうか疑問に思います

from urllib import request

そしてその断片

import urllib.request

あるいはそれらが交換可能であるならば。それらが互換性がある場合、「標準」/「推奨」構文はどれですか(ある場合)。

ありがとうございます。

217
wchargin

参照するときにインポートにアクセスする方法によって異なります。

from urllib import request
# access request directly.
mine = request()

import urllib.request
# used as urllib.request
mine = urllib.request()

簡単にするためにインポートするときや、組み込みのマスキングを避けるために、自分自身で別名を付けることもできます。

from os import open as open_
# lets you use os.open without destroying the 
# built in open() which returns file handles.
198
g.d.d.c

多くの人がすでにimportfromについて説明しているので、実際の違いがあるところで、もう少し詳しく説明したいと思います。

まず最初に、基本的なimport文が何をするのかを正確に説明しましょう。

import X

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

from X import *

モジュールXをインポートし、現在のネームスペースでそのモジュールによって定義されているすべてのパブリックオブジェクト(つまり、_で始まる名前を持たないすべてのもの)への参照を作成します。

あるいは、言い換えれば、このステートメントを実行した後で、単純な(修飾されていない)名前を使用して、モジュールXで定義されているものを参照することができます。しかしX自体は定義されていないので、X.nameは機能しません。 nameがすでに定義されている場合は、新しいバージョンに置き換えられます。 Xの名前が他のオブジェクトを指すように変更されても、モジュールは気付かないでしょう。

これにより、モジュールからのすべての名前がローカル名前空間で使用可能になります。

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

globals()およびlocals()名前空間がosおよびos.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を使用できるはずです。

 >>> 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を削除すると、それらがos.pathに存在していても、osまたは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
>>>

それではfromを見てみましょう。

from

>>> import sys
>>> from os import 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'>

そのためsys.modulesは、import nameを使用してインポートしたときと同じように見えます。

はい。 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()から 'path'を削除しましょう。

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

fromを使用する際の落とし穴

2つの異なるモジュールから同じnameをインポートすると、

>>> import sys
>>> from os import stat
>>> locals()['stat']
<built-in function stat>
>>>
>>> stat
<built-in function stat>

再度shutilからstatをインポートします。

>>>
>>> from shutil import stat
>>> locals()['stat']
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>> stat
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>>

最後のインポートが勝つ

146
James Sapam

機能的にはほとんど違いはありませんが、最初の形式は優先的です。

from urllib import request, parse, error

2番目の形式では、

import urllib.request, urllib.parse, urllib.error

また、完全修飾名を使用して参照する必要がありますが、これはあまり洗練されていません。

30
Karl Barker

違いがあります。場合によっては、そのうちの1つが機能し、もう一方が機能しません。例を示します。次のような構造になっているとします。

foo.py
mylib\
    a.py
    b.py

今、私はb.pya.pyにインポートしたいです。そしてa.pyfooにインポートしたいです。どうやってこれをするの? aに2つのステートメントを書きます。

import b

foo.pyに私はこう書いています:

import mylib.a

さて、これはfoo.pyを実行しようとするとImportErrorを生成します。インタプリタはa.pyimport b)のimport文について文句を言いますが、モジュールbはありません。それではどのようにこれを修正することができますか?このような状況では、aaはどちらもbに含まれるため、mylibのimportステートメントをimport mylib.bに変更しても機能しません。ここでの解決策(少なくとも1つの解決策)は、絶対インポートを使用することです。

from mylib import b

出典: Python:モジュールをインポートするモジュールをインポートする

17
Anas Elghafari

あなたはPython3を使用していますパッケージのurllibでした。どちらの形式でも構いません。どちらの形式のインポートも優先されません。場合によっては、複数のパッケージディレクトリが関係しているときには、以前のfrom x.y.z.a import sを使用することができます。

Urllibパッケージのこの特定のケースでは、2番目の方法import urllib.requesturllib.requestの使用は標準ライブラリがそれをどのように使用するかです。

3
Senthil Kumaran

Python 2.xでは少なくともimport urllib2.urlopenはできません

from urllib2 import urlopenをする必要があります

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib2.urlopen
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named urlopen
>>> import urllib.request
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named request
>>>
1
tkone

Import urllib.requestに対する私の主な不満は、たとえそれがインポートされなくてもurllib.parseを参照できることです。

>>> import urllib3.request
>>> urllib3.logging
<module 'logging' from '/usr/lib/python2.7/logging/__init__.pyc'>

また私の要求はurllib3の下にあります。 Python 2.7.4 ubuntu

0
Anonymous