2015-10-19 15 views
5

Ich habe das folgende Verhalten in Python 3.4.2 beobachtet, und ich kann es nicht erklären. Hoffentlich jemand könnte etwas Licht auf die Sache werfen:Importieren von urllib.parse schlägt fehl, wenn Python über die Befehlszeile ausgeführt wird

In IPython:

In [129]: import urllib 

In [130]: print(urllib.parse) 
<module 'urllib.parse' from '/Users/ashwin/.pyenv/versions/3.4.2/lib/python3.4/urllib/parse.py'> 

Ich habe ein Modul importiert, und eines seiner Attribute gedruckt. Alles funktioniert wie erwartet. Bis jetzt ist das Leben gut.

Jetzt mache ich das Gleiche von der Kommandozeile:

$ python -c 'import urllib; print(urllib.parse)' 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
AttributeError: 'module' object has no attribute 'parse' 

Sagen Sie, was ?! so soll das nicht funktionieren.
Ok, vielleicht ist das ein pythonweites Verhalten; vielleicht werden Module nicht sofort importiert, wenn das Flag -c verwendet wird. Lassen Sie uns ein anderes Modul versuchen:

$ python -c 'import datetime; print(datetime.datetime)' 
<class 'datetime.datetime'> 

Was ?! Wie funktioniert es für datetime und nicht für urllib? Ich benutze die gleiche Version von Python in beiden Orten (3.4.2)

Hat jemand irgendwelche Gedanken dazu?

EDIT:

Per einem der Kommentare:

$ which -a ipython 
/Users/ashwin/.pyenv/shims/ipython 
/Library/Frameworks/Python.framework/Versions/2.7/bin/ipython 
/usr/local/bin/ipython 
/usr/local/bin/ipython 

Und

$ which -a python 
/Users/ashwin/.pyenv/shims/python 
/Library/Frameworks/Python.framework/Versions/2.7/bin/python 
/usr/bin/python 
/usr/bin/python 
+0

Sie möchten die Ausgabe von 'die -a ipython' und' die -a python' – cel

+0

@cel hinzufügen: Ich verstehe nicht, wie das helfen würde, aber ich habe es – inspectorG4dget

+0

So hinzugefügt ' Python -m IPython -c 'Importiere Datetime; print (datetime.datetime) ''und' python -c' import datetime; print (datetime.datetime) gibt andere Ergebnisse? – cel

Antwort

3

Wenn Sie import urllib ausführen, das Modul ein Objekt des urllib Modul erstellt (die eigentlich eine package) ohne seine Submodule zu importieren (parsen, Anfrage etc.).

Sie benötigen das übergeordnete Modulobjekt (urllib) in Ihrem Namespace, wenn Sie mit Attributzugriff auf sein Submodul zugreifen möchten. Außerdem muss das Submodul bereits geladen (importiert) werden. Vom documentation:

wenn Paket spam ein Submodul hat foo nach Import spam.foo wird spam haben ein Attribut foo die das Submodul gebunden ist. [...] Das invariante Halten ist, dass, wenn Sie sys.modules['spam'] und sys.modules['spam.foo'] haben (wie Sie nach dem oben genannten Import wären), das letztere als foo Attribut des ehemaligen erscheinen muss.

Es gibt nur eine Instanz jedes Modul, so werden alle Änderungen an den urllib Modulobjekt (gespeichert in sys.modules['urllib']) überall reflektiert erhalten.

Sie importieren nicht urllib.parse, aber IPython tut. Um dies zu beweisen, werde ich eine Startdatei erstellen:

import urllib 
print('Running the startup file: ', end='') 
try: 
    # After importing 'urllib.parse' ANYWHERE, 
    # 'urllib' will have the 'parse' attribute. 
    # You could also do "import sys; sys.modules['urllib'].parse" 
    urllib.parse 
except AttributeError: 
    print("urllib.parse hasn't been imported yet") 
else: 
    print('urllib.parse has already been imported') 
print('Exiting the startup file.') 

und starten ipython

[email protected]:~$ ipython 
Running urllib/parse.py 
Running the startup file: urllib.parse has already been imported 
Exiting the startup file. 
Python 3.6.0a0 (default:089146b8ccc6, Sep 25 2015, 14:16:56) 
Type "copyright", "credits" or "license" for more information. 

IPython 4.0.0 -- An enhanced Interactive Python. 

Es ist die Nebenwirkung von pydoc während des Starts von IPython Import (which ipython ist /usr/local/bin/ipython):

/usr/local/bin/ipython, line 7: 
    from IPython import start_ipython 
/usr/local/lib/python3.6/site-packages/IPython/__init__.py, line 47: 
    from .core.application import Application 
/usr/local/lib/python3.6/site-packages/IPython/core/application.py, line 24: 
    from IPython.core import release, crashhandler 
/usr/local/lib/python3.6/site-packages/IPython/core/crashhandler.py, line 28: 
    from IPython.core import ultratb 
/usr/local/lib/python3.6/site-packages/IPython/core/ultratb.py, line 90: 
    import pydoc 
/usr/local/lib/python3.6/pydoc.py, line 68: 
    import urllib.parse 

Dies erklärt, warum der folgende Code ausfällt - Sie nur importieren urllib und nichts urllib.parse zu importieren scheinen:

$ python -c 'import urllib; print(urllib.parse)' 

Auf der anderen Seite, die folgenden Befehl funktionieren, weil datetime.datetime sind nicht ein Modul. Es ist eine Klasse, die während import datetime importiert wird.

$ python -c 'import datetime; print(datetime.datetime)' 
+0

Aber wenn ich' pydoc' in IPython versuche, bekomme ich einen 'NameError'.Bedeutet das nicht, dass 'pydoc' beim Start nicht von IPython importiert wurde? – inspectorG4dget

+1

@inspectorG4dget es * wurde * importiert, können Sie überprüfen, ob es bereits in ['sys.modules'] (https://docs.python.org/3/library/sys.html#sys.modules):' ' pydoc 'in sys.modules gibt' True 'zurück. Sie müssen es nur im aktuellen Namespace importieren. – vaultah

+0

Ok, aber "urllib" befindet sich nicht im aktuellen Namespace ODER in 'sys.modules' in IPython. So ist mir noch nicht klar, wie 'urllib.parse' automatisch im Namensraum existiert – inspectorG4dget

0

urllib.parse ist von Python 3 Uhr zur Verfügung. Ich denke, Sie müssen möglicherweise import urllib.parse, nicht . Nicht sicher, ob (wenn) Submodulimport implizit ist.

Ich würde raten IPython importiert urllib.parse beim Start und deshalb ist es verfügbar.

parse ist ein Modul, kein Attribut:

Python 3.4.2 (default, Oct 15 2014, 22:01:37) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import urllib 
>>> urllib.parse 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'module' object has no attribute 'parse' 
>>> import urllib.parse 
>>> urllib.parse 
<module 'urllib.parse' from '/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/parse.py'> 
+1

Ihre Analyse scheint falsch zu sein, da ich Python3.4.2 verwende, selbst wenn ich 'python' von der Kommandozeile aus aufruft. Wie in meinen Pfaden zu sehen ist, stammt der erste Eintrag von 'pyenv', der gerade auf v3.4.2 zeigt. – inspectorG4dget

+0

Probieren Sie' importiere urllib.parse' anstelle von 'importiere urllib' wie vorgeschlagen. –

+0

Danke auch für die Pfadklärung. Ich habe die Frage aktualisiert und die Bits entfernt, die falsch waren. –