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

时间:2016-05-27 19:40:21

标签: python python-import python-module

在真正需要import datetime之后不小心输入from datetime import datetime之后,我想知道是否有可能破解并让前者做后者。

即,重新创建此行为(在新打开的解释器会话中):

$ python -ic ''
>>> import datetime
>>> datetime(2016, 5, 27)
datetime.datetime(2016, 5, 27, 0, 0)

非常接近假装下面的“可调用模块”:

>>> import dt
>>> dt(2016, 5, 27)
datetime.datetime(2016, 5, 27, 0, 0)

这是这样实现的:

# 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模块{ {1}}。

我们如何从影子模块本身暂时取消隐藏内置或网站包模块?在这种情况下是否有任何间接的方式来获取核心datetime.py(可能类似于我们仍然可以访问datetime,即使重定向sys.__stdout__也是如此?

免责声明:绝不表示这是一个理智的想法 - 只是感兴趣,如果可能

2 个答案:

答案 0 :(得分:7)

我们走了:

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)

test.py(住在datetime.py旁边):

import datetime

print(datetime(1, 2, 3))
print(datetime.timedelta(days=1))
print(datetime.now())

运行test.py,输出:

0001-02-03 00:00:00
1 day, 0:00:00
2016-05-27 23:16:30.954270

它也适用于from datetime import datetime, timedelta等。

这特别是hacky和脆弱,将取决于你的分布。例如,显然它不适用于IPython。您必须在标准库模块之前导入datetime.py

要理解奇怪的事情,如果将变量std_datetime(日期时间模块对象)重命名为datetime,那么datetime.datetime不再是类,而是datetime is datetime.datetime is datetime.datetime.datetime ...。如果有人能解释为什么会这样,我很乐意听到它。

(请注意,下面的第一条评论是在我到达最终版本之前)

答案 1 :(得分:2)

通过对原始想法的一点修改,这实际上适用于python3:

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