Python 如何使语句“import datetime”绑定datetime类型而不是datetime模块?

Python 如何使语句“import datetime”绑定datetime类型而不是datetime模块?,python,python-import,python-module,Python,Python Import,Python Module,当真正需要的是datetime import datetime中的时,我意外地输入了很多次import datetime,之后我想知道是否有可能破解并让前者完成后者 也就是说,要重新创建此行为(在新打开的解释器会话中): 非常接近于在下面伪造一个“可调用模块”: 它是这样实现的: # dt.py import sys import datetime class CallableModule(object): def __init__(self, thing): self

当真正需要的是datetime import datetime中的
时,我意外地输入了很多次
import datetime
,之后我想知道是否有可能破解并让前者完成后者

也就是说,要重新创建此行为(在新打开的解释器会话中):

非常接近于在下面伪造一个“可调用模块”:

它是这样实现的:

# dt.py
import sys
import datetime

class CallableModule(object):
    def __init__(self, thing):
        self.thing = thing
    def __call__(self, *args, **kwargs):
        return self.thing.__call__(*args, **kwargs)

sys.modules['dt'] = CallableModule(datetime.datetime)
但是,如果我尝试为模块使用文件名
datetime.py
,它就不起作用了,而且当我自己的文件也被称为
datetime.py
时,我还找不到任何破解内置datetime模块的方法

如何从隐藏模块本身中临时取消隐藏内置模块或站点包模块?在这种情况下,是否有任何间接的方法来获取核心
datetime
(可能类似于即使
sys.stdout
被重定向,我们仍然可以访问
sys.stdout

免责声明:决不表示这是一个明智的想法——只要有可能就感兴趣

我们开始:

datetime.py

import sys
import imp
import os

path = [p for p in sys.path if p != os.path.dirname(__file__)]
f, pathname, desc = imp.find_module('datetime', path)
std_datetime = imp.load_module('datetime', f, pathname, desc)
# if this^ is renamed to datetime, everything breaks!
f.close()

class CallableModule(object):

    def __init__(self, module, fn):
        self.module = module
        self.fn = fn

    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

    def __getattr__(self, item):
        try:
            return getattr(self.fn, item)
        except AttributeError:
            return getattr(self.module, item)

sys.modules['datetime'] = CallableModule(std_datetime, std_datetime.datetime)
import datetime

print(datetime(1, 2, 3))
print(datetime.timedelta(days=1))
print(datetime.now())
test.py
(位于
datetime.py
旁边):

运行
test.py
,输出:

0001-02-03 00:00:00
1 day, 0:00:00
2016-05-27 23:16:30.954270
它还适用于从日期时间导入日期时间、时间增量等的

这是特别黑客和脆弱的,将取决于您的分发。例如,显然它与IPython不起作用。必须在标准库模块之前导入
datetime.py

为了理解这样做有多么奇怪,如果变量
std_datetime
(datetime模块对象)被重命名为
datetime
,那么
datetime.datetime
不再是类,而是
datetime是datetime.datetime是datetime.datetime.datetime…
。如果有人能解释为什么会发生这种情况,我很想听


(请注意,下面的第一条评论是在我获得最终版本之前发表的)

对原始想法进行了一点修改,这实际上适用于python3:

# datetime.py
import sys, _datetime
sys.modules['datetime'] = _datetime.datetime

我打算建议进入“real”
datetime.py并添加
import sys;sys.modules['datetime']=datetime
,但后来我意识到
datetime
是一个C模块。我不知道这与问题中的代码相比增加了什么,因为问题中的代码已经是这样了。显然,你也可以在linux上的python3上的moduleWorks内部编写
sys.modules
。有趣的是,它在ipython上不起作用——大概是因为ipython的startup在您有机会导入datetime模块之前就已经导入了@wim查看如果您先删除系统模块['datetime']
会发生什么。
0001-02-03 00:00:00
1 day, 0:00:00
2016-05-27 23:16:30.954270
# datetime.py
import sys, _datetime
sys.modules['datetime'] = _datetime.datetime