在真正需要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__
也是如此?
免责声明:绝不表示这是一个理智的想法 - 只是感兴趣,如果可能。
答案 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