`from... import` vs` import.`

Мне интересно, есть ли разница между фрагментом кода

from urllib import request

и фрагмент

import urllib.request

или если они взаимозаменяемы. Если они взаимозаменяемы, что является "стандартным" / "предпочтительным" синтаксисом (если есть)?

Спасибо!

Ответ 1

Это зависит от того, как вы хотите получить доступ к импорту, когда ссылаетесь на него.

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.

Ответ 2

Многие люди уже объяснили import vs from, поэтому я хочу попытаться объяснить немного больше под капотом, где фактическая разница лежит.

Прежде всего, позвольте мне объяснить, что делают основные операторы импорта.

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

Проверьте 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() пространство имен dict с именем 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'>
 >>>

& hellip; но не path:

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

Как только вы удалите пространство имен os из locals(), вы не сможете получить доступ к 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
>>>

Теперь посмотрим на from.

from

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

Итак, sys.modules выглядит так же, как при импортировании с помощью import name.

Хорошо. Позвольте проверить, как это выглядит: locals() и globals() namespace dicts:

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

Одна ошибка при использовании from

Когда вы импортируете те же name из двух разных модулей:

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

Импортировать stat из shutil еще раз:

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

ПОСЛЕДНИЙ ИМПОРТ ВЫИГРАТЬ

Ответ 3

Там очень мало различий в функциональности, но первая форма является предпочтительной, так как вы можете сделать

from urllib import request, parse, error

где во второй форме, которая должна быть

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

и вам нужно будет ссылаться, используя полное имя, которое менее элегантно.

Ответ 4

Есть разница. В некоторых случаях один из них будет работать, а другой - нет. Вот пример: скажем, мы имеем следующую структуру:

foo.py
mylib\
    a.py
    b.py

Теперь я хочу импортировать b.py в a.py. И я хочу импортировать a.py в foo. Как мне это сделать? Два утверждения: В a пишу:

import b

in foo.py Пишу:

import mylib.a

Ну, это приведет к созданию ImportError при попытке запустить foo.py. Интерпретатор будет жаловаться на оператор импорта в a.py(import b), говорящий, что нет модуля b. Итак, как это можно исправить? В такой ситуации изменение инструкции import в для импорта mylib.b не будет работать, так как a и b находятся в lib. Решение здесь (или хотя бы одно решение) заключается в использовании абсолютного импорта:

from lib import b

Источник: Python: импорт модуля, который импортирует модуль

Ответ 5

Вы используете Python3, были urllib в пакете. Обе формы приемлемы, и ни одна форма импорта не является предпочтительной по сравнению с другой. Иногда, когда есть несколько каталогов пакетов, вы можете использовать предыдущий from x.y.z.a import s

В этом конкретном случае с пакетом urllib второй способ import urllib.request и использование urllib.request - это то, как стандартная библиотека использует его равномерно.

Ответ 6

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

Ответ 7

Моя основная жалоба с импортом 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