Python 存在同名模块时从内置库导入

Python 存在同名模块时从内置库导入,python,import,Python,Import,情况: -“我的项目”文件夹中有一个名为“日历”的模块 -我想使用Python库中的内置日历类 -当我使用from calendar import calendar时,它会抱怨,因为它试图从我的模块加载 我做了一些搜索,但似乎找不到解决问题的方法 不必重命名我的模块,你有什么想法吗?解决这个问题的唯一方法是自己劫持内部导入机器。这并不容易,而且充满了危险。你应该不惜一切代价避免圣杯形状的灯塔,因为危险太大了 改名模块 如果您想了解如何劫持内部进口机器,您可以在这里了解如何做到这一点:

情况: -“我的项目”文件夹中有一个名为“日历”的模块 -我想使用Python库中的内置日历类 -当我使用from calendar import calendar时,它会抱怨,因为它试图从我的模块加载

我做了一些搜索,但似乎找不到解决问题的方法


不必重命名我的模块,你有什么想法吗?

解决这个问题的唯一方法是自己劫持内部导入机器。这并不容易,而且充满了危险。你应该不惜一切代价避免圣杯形状的灯塔,因为危险太大了

改名模块

如果您想了解如何劫持内部进口机器,您可以在这里了解如何做到这一点:

有时有很好的理由陷入这种危险。你给出的理由不在其中。重命名您的模块

如果您走的是一条危险的道路,那么您将遇到的一个问题是,当您加载一个模块时,它会以一个“正式名称”结束,这样Python就可以避免再次解析该模块的内容。模块的“官方名称”到模块对象本身的映射可以在
sys.modules
中找到

这意味着,如果您在一个地方导入日历,那么导入的任何模块都将被视为具有官方名称的模块,并且所有其他尝试导入日历的尝试,包括在作为主要Python库一部分的其他代码中,都将获得该日历

可以使用Python 2.x中的设计客户导入器,这会导致从某些路径加载的模块首先在
sys.modules
或类似内容中查找它们导入的模块。但这是一件非常棘手的事情,而且无论如何在Python3.x中都不起作用

有一个非常丑陋和可怕的事情,你可以做,不涉及挂钩的进口机制。这可能是你不应该做的事情,但它可能会起作用。它将您的
日历
模块转变为系统日历模块和日历模块的混合体。谢谢你的帮助。将其放在
calendar.py
文件的开头:

import sys

def copy_in_standard_module_symbols(name, local_module):
    import imp

    for i in range(0, 100):
        random_name = 'random_name_%d' % (i,)
        if random_name not in sys.modules:
            break
        else:
            random_name = None
    if random_name is None:
        raise RuntimeError("Couldn't manufacture an unused module name.")
    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(random_name, f, pathname, desc)
    f.close()
    del sys.modules[random_name]
    for key in module.__dict__:
        if not hasattr(local_module, key):
            setattr(local_module, key, getattr(module, key))

copy_in_standard_module_symbols('calendar', sys.modules[copy_in_standard_module_symbols.__module__])

解决这个问题的唯一办法是自己劫持内部进口机器。这并不容易,而且充满了危险。你应该不惜一切代价避免圣杯形状的灯塔,因为危险太大了

改名模块

如果您想了解如何劫持内部进口机器,您可以在这里了解如何做到这一点:

有时有很好的理由陷入这种危险。你给出的理由不在其中。重命名您的模块

如果您走的是一条危险的道路,那么您将遇到的一个问题是,当您加载一个模块时,它会以一个“正式名称”结束,这样Python就可以避免再次解析该模块的内容。模块的“官方名称”到模块对象本身的映射可以在
sys.modules
中找到

这意味着,如果您在一个地方导入日历,那么导入的任何模块都将被视为具有官方名称的模块,并且所有其他尝试导入日历的尝试,包括在作为主要Python库一部分的其他代码中,都将获得该日历

可以使用Python 2.x中的设计客户导入器,这会导致从某些路径加载的模块首先在
sys.modules
或类似内容中查找它们导入的模块。但这是一件非常棘手的事情,而且无论如何在Python3.x中都不起作用

有一个非常丑陋和可怕的事情,你可以做,不涉及挂钩的进口机制。这可能是你不应该做的事情,但它可能会起作用。它将您的
日历
模块转变为系统日历模块和日历模块的混合体。谢谢你的帮助。将其放在
calendar.py
文件的开头:

import sys

def copy_in_standard_module_symbols(name, local_module):
    import imp

    for i in range(0, 100):
        random_name = 'random_name_%d' % (i,)
        if random_name not in sys.modules:
            break
        else:
            random_name = None
    if random_name is None:
        raise RuntimeError("Couldn't manufacture an unused module name.")
    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(random_name, f, pathname, desc)
    f.close()
    del sys.modules[random_name]
    for key in module.__dict__:
        if not hasattr(local_module, key):
            setattr(local_module, key, getattr(module, key))

copy_in_standard_module_symbols('calendar', sys.modules[copy_in_standard_module_symbols.__module__])

更改导入路径:

import sys
save_path = sys.path[:]
sys.path.remove('')
import calendar
sys.path = save_path

更改导入路径:

import sys
save_path = sys.path[:]
sys.path.remove('')
import calendar
sys.path = save_path

实际上,解决这个问题相当容易,但实现总是有点脆弱,因为它依赖于python导入机制的内部,并且在未来的版本中可能会发生更改

(以下代码显示了如何加载本地和非本地模块以及它们如何共存)


如果可能的话,最好的解决方案是避免使用与标准库或内置模块名称相同的名称命名模块。

实际上,解决这一问题相当容易,但实现总是有点脆弱,因为这取决于python导入机制的内部结构,并且它们在未来版本中可能会发生更改

(以下代码显示了如何加载本地和非本地模块以及它们如何共存)


如果可能,最好的解决方案是避免使用与标准库或内置模块名称相同的名称命名模块。

无需更改模块名称。相反,您可以使用绝对导入来更改导入行为。例如,我导入套接字模块,如下所示:

from __future__ import absolute_import
import socket

这仅适用于Python2.5及更高版本;它启用了Python 3.0及更高版本中默认的行为。Pylint会抱怨代码,但它完全有效。

无需更改模块名称。相反,您可以使用绝对导入来更改导入行为。例如,我导入套接字模块,如下所示:

from __future__ import absolute_import
import socket
这仅适用于Python2.5及更高版本;这是一种默认的行为
import sys
from mysql.utilities import import_non_local         # where I put the above function (mysql/utilities/__init__.py)
import_non_local('mysql.connector', sys.modules[__name__])
# This unmodified line further down in the file now works just fine because mysql.connector has actually become part of the namespace
self.db_conn = mysql.connector.connect(**parameters)