2015-10-19 14 views
5

Tôi đã quan sát hành vi sau đây trong python 3.4.2 và tôi unableto giải thích nó. Hy vọng rằng ai đó có thể làm sáng tỏ về vấn đề này:nhập urllib.parse không thành công khi Python chạy từ dòng lệnh

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

tôi đã nhập một mô-đun, và in một trong những thuộc tính của nó. Mọi thứ hoạt động như mong đợi. Cho đến nay, cuộc sống là tốt.

Bây giờ, tôi làm điều tương tự từ dòng lệnh:

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

Nói những gì ?! đó không phải là cách làm việc đó.
Ok, có thể đây là một hành vi trên toàn con trăn; có thể mô-đun không được nhập ngay lập tức khi sử dụng cờ -c. Hãy thử một mô-đun khác:

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

Cái gì ?! Làm thế nào nó hoạt động cho datetime và không cho urllib? Tôi đang sử dụng cùng một phiên bản của python ở cả hai nơi (3.4.2)

Có ai có bất kỳ suy nghĩ nào về điều này không?

EDIT:

mỗi một trong những nhận xét:

$ 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 

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

bạn có thể muốn thêm sản lượng của 'mà -a ipython' và 'mà -a python' – cel

+0

@cel: Tôi không hiểu làm thế nào mà có thể giúp, nhưng tôi đã thêm nó – inspectorG4dget

+0

Vì vậy' python -m IPython -c 'nhập datetime; in (datetime.datetime) ''và' python -c' nhập datetime; in (datetime.datetime) ''cho kết quả khác nhau? – cel

Trả lời

3

Khi bạn chạy import urllib, nó tạo ra các đối tượng mô-đun của các mô-đun urllib (mà thực sự là một package) mà không cần nhập khẩu các môđun con của nó (phân tích, yêu cầu v.v.)

Bạn cần đối tượng mô-đun chính (urllib) nằm trong không gian tên của bạn nếu bạn muốn truy cập mô-đun con bằng cách sử dụng quyền truy cập thuộc tính. Ngoài ra, mô-đun con đó phải đã được tải (đã nhập). Từ documentation:

nếu gói spam có một submodule foo, sau khi nhập spam.foo, spam sẽ có một thuộc tính foo được ràng buộc với submodule. [...] Việc giữ bất biến là nếu bạn có sys.modules['spam']sys.modules['spam.foo'] (như bạn sẽ sau khi nhập ở trên), thì phải xuất hiện dưới dạng thuộc tính foo của trước đây.

Chỉ có một trường hợp của mỗi mô-đun, do đó mọi thay đổi được thực hiện cho đối tượng mô-đun urllib (được lưu trữ trong sys.modules['urllib']) được phản ánh ở mọi nơi.

Bạn không nhập urllib.parse, nhưng IPython hiện. Để chứng minh điều này tôi sẽ tạo ra một tập tin khởi động:

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

và khởi động 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. 

Đây là tác dụng phụ của nhập khẩu pydoc trong khởi động của IPython (which ipython/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 

Điều này giải thích tại sao đoạn code dưới đây không - bạn chỉ nhập urllib và không có gì dường như nhập khẩu urllib.parse:

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

Mặt khác, các công trình lệnh sau vì datetime.datetimekhông một mô-đun. Đó là một lớp học được nhập khẩu trong thời gian import datetime.

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

Nhưng nếu tôi thử' pydoc' trong IPython, tôi nhận được 'NameError'.Điều đó không có nghĩa là 'pydoc' chưa được IPython nhập vào lúc khởi động? – inspectorG4dget

+1

@ inspectorG4dget it * has * được nhập, bạn có thể kiểm tra xem nó đã có trong ['sys.modules'] (https://docs.python.org/3/library/sys.html#sys.modules):' ' pydoc 'trong sys.modules' trả về 'True'. Bạn chỉ cần nhập nó vào không gian tên hiện tại. – vaultah

+0

Ok, nhưng 'urllib' không có trong không gian tên hiện tại HOẶC trong' sys.modules' trong IPython. Vì vậy, tôi vẫn không rõ ràng về cách 'urllib.parse' tự động tồn tại trong không gian tên – inspectorG4dget

0

urllib.parse có sẵn từ Python 3 trở đi. Tôi nghĩ bạn có thể cần phải import urllib.parse, không phải import urllib. Không chắc chắn nếu (khi) submodule nhập khẩu là tiềm ẩn.

Tôi đoán IPython sẽ nhập urllib.parse khi khởi động và đó là lý do tại sao tính năng này khả dụng.

parse là một mô-đun không phải là một thuộc tính:

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

Phân tích của bạn có vẻ không chính xác, vì tôi đang sử dụng python3.4.2 ngay cả khi tôi gọi 'python' từ dòng lệnh. Như đã thấy trong các đường dẫn của tôi, mục đầu tiên là từ 'pyenv', hiện đang trỏ đến v3.4.2 – inspectorG4dget

+0

Thử' import urllib.parse' thay vì 'import urllib' như được gợi ý. –

+0

Cũng cảm ơn bạn đã làm rõ con đường. Tôi đã cập nhật câu hỏi và xóa các bit không chính xác. –

Các vấn đề liên quan