`from … import` vs `import .` [duplicat] (Programare, Python, Import, Sintaxă, Modul, Python Import)

wchargin a intrebat.
a intrebat.

Mă întreb dacă există vreo diferență între fragmentul de cod

from urllib import request

și fragmentul

import urllib.request

sau dacă acestea sunt interschimbabile. Dacă sunt interschimbabile, care este sintaxa „standard”/”preferată” (dacă există una)?

Comentarii

  • Nu sunt un expert în importuri, așa că nu voi lăsa un răspuns, dar există o diferență cu privire la modul în care lucrurile intră în sys.modules: aruncați o privire la acest răspuns (la sfârșit). (Poate că există cineva care poate explica mai bine decât mine) –  > Por Rik Poggi.
6 răspunsuri
g.d.d.d.c

Depinde de modul în care doriți să accesați importul atunci când faceți referire la el.

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

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

De asemenea, puteți să vă aliasați singuri lucrurile atunci când importați pentru simplitate sau pentru a evita mascarea built-in-urilor:

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

Comentarii

  • Tocmai am încercat să import urllib.request și nu funcționează deloc (python 2.6.5 Ubuntu). –  > Por tkone.
  • Ar trebui să folosiți o subliniere la sfârșit (mai degrabă decât la început) pentru a evita ciocnirea cu built-ins. –  > Por deadly.
  • @deadly – obicei prost – previne un avertisment IDE în Eclipse pentru a utiliza uneori un underscore de conducere. Mulțumesc. –  > Por g.d.d.d.c.
  • @g.d.d.d.c: Convenția „o singură subliniere la sfârșit” este specificată în mod explicit de PEP 8 (de două ori). Dacă Eclipse produce avertismente enervante cu privire la codul corect, atunci avem un IDE prost, nu un obicei prost. –  > Por wchargin.
  • @tkone În Python 3, urllib2 a fost mutat în urllib.request. –  > Por Arcanum.
James

Mulți oameni au explicat deja despre import vs from, , așa că vreau să încerc să explic un pic mai mult sub capotă, unde se află diferența reală.

Mai întâi de toate, permiteți-mi să explic exact ce fac declarațiile de import de bază.

import X

Importă modulul X, , și creează o referință la acel modul în spațiul de nume curent. Apoi, trebuie să definiți calea completată a modulului pentru aaccesa un anumit atribut sau metodă din interiorul modulului (de ex:X.name sau X.attribute)

from X import *

Importă modulul X, și creează referințe la toate obiectele publice definite de modulul respectiv în spațiul de nume curent (adică tot ceea ce nu are un nume care începe cu _) sau orice nume pe care l-ați menționat.

Sau, cu alte cuvinte, după ce ați executat această instrucțiune, puteți utiliza pur și simplu un nume simplu (necalificat) pentru a vă referi la lucrurile definite în modulul X.but X în sine nu este definit, așa că X.name nu funcționează. Și dacă namea fost deja definită, aceasta este înlocuită cu noua versiune. Iar dacă numele din X este schimbat pentru a indica un alt obiect, modulul dvs. nu va observa.

Acest lucru face ca toate numele din modul să fie disponibile în spațiul de nume local.

Acum să vedem ce se întâmplă atunci când facem import X.Y:

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

Verificați sys.modules cu numele os și 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'>

Verificați globals() și locals() namespace dict cu numele os și 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'
>>>    

Din exemplul de mai sus, am constatat că numai os este adăugat la spațiile de nume locale și globale.Așadar, ar trebui să putem utiliza 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'>
 >>>

…dar nu și path:

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

Odată ce ștergeți os de pe locals() nu veți mai putea accesa nici spațiul de nume os sau la os.path, chiar dacă ele există în 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
>>>

Acum să ne uităm la from.

from

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

Verificați sys.modules cu numele os și 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'>

Deci sys.modules arată la fel ca atunci când am importat folosind import name.

Bine. Să verificăm ce înseamnă locals() și globals() și 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'
>>>

Puteți accesa folosind path, , dar nu și prin 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
>>>
 

Să ștergem ‘path’ din locals():

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

Un ultim exemplu de utilizare a aliasing-ului:

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

Și nici o cale definită:

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

O capcană legată de utilizarea from

Atunci când importați același name din două module diferite:

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

Importă stat din shutil din nou:

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

ULTIMUL IMPORT VA CÂȘTIGA

Comentarii

  • Într-adevăr, dar pentru mine este un pic confuz cu toate aceste spații de nume și așa mai departe. Așadar, prefer să folosesc doar import x și apoi x.what_is_necessary. După umila mea părere, cred că este mai ușor de citit și mai ușor de evitat confuzia, iar în acest fel se evită cu siguranță conflictele de nume, ambiguitatea și tot felul de lucruri… nu-i așa? –  > Por udarH3.
  • Îmi place acest răspuns, deoarece învață cum să prinzi pești în loc să oferi pește. –  > Por Dana.
  • Ce înseamnă `de la . import <classyouwant>’? Nu sunt sigur la ce se referă punctul. –  > Por Azurespot.
  • Punctul indică faptul că este un import relativ, unu înseamnă directorul curent, doi înseamnă directorul părinte și așa mai departe în sus în arbore. –  > Por dragon788.
Anas Elghafari

Există o diferență. În unele cazuri, una dintre acestea va funcționa și cealaltă nu. Iată un exemplu: să spunem că avem următoarea structură:

foo.py
mylib
    a.py
    b.py

Acum, vreau să importăm b.py în a.py. Și vreau să import a.py în foo. Cum pot face acest lucru? Două declarații, în a Scriu:

import b

În foo.py Scriu:

import mylib.a

Ei bine, acest lucru va genera un ImportError atunci când se încearcă să se execute foo.py. Interpretul se va plânge de declarația de import din a.py (import b), spunând că nu există un modul b. Deci, cum se poate rezolva acest lucru? Într-o astfel de situație, schimbarea declarației de import din a în import mylib.bnu va funcționa, deoarece a și b sunt ambele în mylib. Soluția în acest caz (sau cel puțin o soluție) este de a utiliza importul absolut:

from mylib import b

Sursa: Python: importarea unui modul care importă un modul

Senthil Kumaran

Folosiți Python3 au fost urllib în pachet. Ambele forme sunt acceptabile și nicio formă de import nu este preferată față de cealaltă. Uneori, atunci când sunt implicate mai multe directoare de pachete, este posibil să folosiți prima formă from x.y.z.a import s

În acest caz particular cu pachetul urllib, a doua modalitate import urllib.request și utilizarea lui urllib.request este modul în care biblioteca standard îl utilizează în mod uniform.

tkone

În python 2.x cel puțin nu puteți face import urllib2.urlopen

Trebuie să faceți 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
>>>

Comentarii

  • Ei bine, asta pentru că urlopen este o funcție, nu-i așa? Ar fi ca și cum ai încerca să import os.chdir-cum ar fi mesajul de eroare care spune, pe bună dreptate, „No module named chdir„… pentru că nu este un modul! –  > Por wchargin.
Anonimul

Principala mea plângere cu import urllib.request este că puteți face în continuare referire la urllib.parse chiar dacă nu este importat.

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

De asemenea, request pentru mine este sub urllib3. Python 2.7.4 ubuntu