如果文件名为 email.py 或 logging.py,则无法使用 Python 请求模块?
Cannot use Python Requests module if file is named email.py or logging.py?
我有一个简单的测试脚本:
import requests
response = requests.get('http://httpbin.org/get')
print response.text
当 python 脚本命名为 test.py
时有效,但如果命名为 email.py
或 logging.py
:
则失败
Traceback (most recent call last):
File "./email.py", line 3, in <module>
import requests
File "/usr/lib/python2.7/dist-packages/requests/__init__.py", line 53, in <module>
from urllib3.contrib import pyopenssl
File "/usr/lib/python2.7/dist-packages/urllib3/__init__.py", line 16, in <module>
from .connectionpool import (
File "/usr/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 59, in <module>
from .request import RequestMethods
File "/usr/lib/python2.7/dist-packages/urllib3/request.py", line 12, in <module>
from .filepost import encode_multipart_formdata
File "/usr/lib/python2.7/dist-packages/urllib3/filepost.py", line 15, in <module>
from .fields import RequestField
File "/usr/lib/python2.7/dist-packages/urllib3/fields.py", line 7, in <module>
import email.utils
File "/home/ubuntu/temp/email.py", line 4, in <module>
response = requests.get('http://httpbin.org/get')
AttributeError: 'module' object has no attribute 'get'
似乎 requests
导入了 urllib3
,它导入了 email
内置模块。为什么 Python 找不到 the built-in email
module first,而不是在当前路径中查找 email.py
?
有没有办法让它工作,或者我是否只需要始终避免将我的 Python 脚本命名为任何可能由任何依赖项导入的内置模块?
这不是请求的问题。
"problem" 来自 Python。 email
和logging
是标准模块,除非你理解并愿意解决冲突,否则不建议将自己的模块命名为相同的。
首先,正如您在评论中指出的那样,Python 检查具有该名称的 'built-in' 模块。并非标准库中的所有模块都是 'built-in'。您可以通过以下方式查看列表:
print sys.builtin_module_names
如果在那里找不到,搜索的顺序由 Burhan 在此处接受的答案概述:
What is the extent of the import statement in Python
Python searches for things it can import in the following order:
- From the directory where the script was executed.
- From the directories in the PYTHONPATH environment variable (if its set).
- From the system-wide Python installation's module directory.
对于您的情况,电子邮件不是内置的,因此首先检查当前目录。
所以,是的,不要隐藏 python 库名称。从技术上讲,您可以隐藏内置模块的名称,但请不要这样做。让人Python哭泣。
看看 sys.path
,您会看到 ''
作为第一个条目:
>>> import sys
>>> sys.path
['',
'/.../3.3/lib/python33.zip',
'/.../3.3/lib/python3.3',
'/.../3.3/lib/python3.3/plat-darwin',
'/.../3.3/lib/python3.3/lib-dynload',
'/.../3.3/lib/python3.3/site-packages']
那''
就是当前目录。
您可以修改 sys.path
,但从长远来看,不给 python 匹配内置模块的文件名是一个更明智的决定。
Python 首先在当前目录中查找模块的原因是 Python 就是这样工作的。如果您查看 sys.path
,您会发现它的第一个元素几乎总是 ''
,表示当前目录。这适用于除内置模块之外的所有内容,内置模块在解释器启动时为 "imported"。 (它们并没有真正导入,只是分配到 sys.modules
。)
一般来说,您不应将自己的模块命名为与您正在使用的其他模块相同的名称(无论它们是否带有 Python)。我倾向于将我的首字母写在我正在使用的脚本上,只是为了避免这个陷阱。
当然,您可以直接操作 sys.path
,这样它就不会在当前目录中查找模块:
import sys
if not sys.path[0]:
del sys.path[0]
import requests
请注意,您只需要在导入时删除 ''
条目 。 您应该在导入后将其放回原处,以防您需要导入从您自己的脚本目录中删除同名模块。上下文管理器对此很方便。
import sys
from contextlib import contextmanager
@contextmanager
def no_cwd_imports():
old_path = sys.path[:]
if not sys.path[0]:
del sys.path[0]
try:
yield
finally:
sys.path[:] = old_path
with no_cwd_imports():
import requests
我有一个简单的测试脚本:
import requests
response = requests.get('http://httpbin.org/get')
print response.text
当 python 脚本命名为 test.py
时有效,但如果命名为 email.py
或 logging.py
:
Traceback (most recent call last):
File "./email.py", line 3, in <module>
import requests
File "/usr/lib/python2.7/dist-packages/requests/__init__.py", line 53, in <module>
from urllib3.contrib import pyopenssl
File "/usr/lib/python2.7/dist-packages/urllib3/__init__.py", line 16, in <module>
from .connectionpool import (
File "/usr/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 59, in <module>
from .request import RequestMethods
File "/usr/lib/python2.7/dist-packages/urllib3/request.py", line 12, in <module>
from .filepost import encode_multipart_formdata
File "/usr/lib/python2.7/dist-packages/urllib3/filepost.py", line 15, in <module>
from .fields import RequestField
File "/usr/lib/python2.7/dist-packages/urllib3/fields.py", line 7, in <module>
import email.utils
File "/home/ubuntu/temp/email.py", line 4, in <module>
response = requests.get('http://httpbin.org/get')
AttributeError: 'module' object has no attribute 'get'
似乎 requests
导入了 urllib3
,它导入了 email
内置模块。为什么 Python 找不到 the built-in email
module first,而不是在当前路径中查找 email.py
?
有没有办法让它工作,或者我是否只需要始终避免将我的 Python 脚本命名为任何可能由任何依赖项导入的内置模块?
这不是请求的问题。
"problem" 来自 Python。 email
和logging
是标准模块,除非你理解并愿意解决冲突,否则不建议将自己的模块命名为相同的。
首先,正如您在评论中指出的那样,Python 检查具有该名称的 'built-in' 模块。并非标准库中的所有模块都是 'built-in'。您可以通过以下方式查看列表:
print sys.builtin_module_names
如果在那里找不到,搜索的顺序由 Burhan 在此处接受的答案概述:
What is the extent of the import statement in Python
Python searches for things it can import in the following order:
- From the directory where the script was executed.
- From the directories in the PYTHONPATH environment variable (if its set).
- From the system-wide Python installation's module directory.
对于您的情况,电子邮件不是内置的,因此首先检查当前目录。
所以,是的,不要隐藏 python 库名称。从技术上讲,您可以隐藏内置模块的名称,但请不要这样做。让人Python哭泣。
看看 sys.path
,您会看到 ''
作为第一个条目:
>>> import sys
>>> sys.path
['',
'/.../3.3/lib/python33.zip',
'/.../3.3/lib/python3.3',
'/.../3.3/lib/python3.3/plat-darwin',
'/.../3.3/lib/python3.3/lib-dynload',
'/.../3.3/lib/python3.3/site-packages']
那''
就是当前目录。
您可以修改 sys.path
,但从长远来看,不给 python 匹配内置模块的文件名是一个更明智的决定。
Python 首先在当前目录中查找模块的原因是 Python 就是这样工作的。如果您查看 sys.path
,您会发现它的第一个元素几乎总是 ''
,表示当前目录。这适用于除内置模块之外的所有内容,内置模块在解释器启动时为 "imported"。 (它们并没有真正导入,只是分配到 sys.modules
。)
一般来说,您不应将自己的模块命名为与您正在使用的其他模块相同的名称(无论它们是否带有 Python)。我倾向于将我的首字母写在我正在使用的脚本上,只是为了避免这个陷阱。
当然,您可以直接操作 sys.path
,这样它就不会在当前目录中查找模块:
import sys
if not sys.path[0]:
del sys.path[0]
import requests
请注意,您只需要在导入时删除 ''
条目 。 您应该在导入后将其放回原处,以防您需要导入从您自己的脚本目录中删除同名模块。上下文管理器对此很方便。
import sys
from contextlib import contextmanager
@contextmanager
def no_cwd_imports():
old_path = sys.path[:]
if not sys.path[0]:
del sys.path[0]
try:
yield
finally:
sys.path[:] = old_path
with no_cwd_imports():
import requests