4

假设您在一个名为 logging.py 的文件中。如果您尝试导入标准日志记录模块,您最终会导入您所在的文件。如何从这里导入标准日志记录模块?

4

4 回答 4

2

您总是可以从 中删除当前目录sys.path,但这是非常骇人听闻的,而且不可靠。经过测试,我意识到如果文件正在运行,这可以工作(作为__main__,但如果它正在被导入,这是非常不可靠的)。

我认为你能做的最好的事情就是不要用 std lib 包使用的名称来命名你的文件。

于 2012-09-12T22:04:20.020 回答
1

那么您可以使用imp绝对路径加载模块。

import imp
help(imp.load_module)
load_module(...)
    load_module(name, file, filename, (suffix, mode, type)) -> module
    Load a module, given information returned by find_module().
    The module name must include the full package name, if any.

在我的 Mac 上,我这样做了:

import imp
py_logging = imp.load_module('logging', None, '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging', ('', '', 5))
dir(py_logging)
['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', 'FATAL', 'FileHandler', 'Filter', 'Filterer', 'Formatter', 'Handler', 'INFO', 'LogRecord', 'Logger', 'LoggerAdapter', 'Manager', 'NOTSET', 'PlaceHolder', 'RootLogger', 'StreamHandler', 'WARN', 'WARNING', '__all__', '__author__', '__builtins__', '__date__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__status__', '__version__', '_acquireLock', '_defaultFormatter', '_handlerList', '_handlers', '_levelNames', '_lock', '_loggerClass', '_releaseLock', '_srcfile', '_startTime', 'addLevelName', 'atexit', 'basicConfig', 'cStringIO', 'codecs', 'critical', 'currentframe', 'debug', 'disable', 'error', 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass', 'info', 'log', 'logProcesses', 'logThreads', 'makeLogRecord', 'os', 'raiseExceptions', 'root', 'setLoggerClass', 'shutdown', 'string', 'sys', 'thread', 'threading', 'time', 'traceback', 'types', 'warn', 'warning']

dir(logging)
['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', 'FATAL', 'FileHandler', 'Filter', 'Filterer', 'Formatter', 'Handler', 'INFO', 'LogRecord', 'Logger', 'LoggerAdapter', 'Manager', 'NOTSET', 'PlaceHolder', 'RootLogger', 'StreamHandler', 'WARN', 'WARNING', '__all__', '__author__', '__builtins__', '__date__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__status__', '__version__', '_acquireLock', '_defaultFormatter', '_handlerList', '_handlers', '_levelNames', '_lock', '_loggerClass', '_releaseLock', '_srcfile', '_startTime', 'addLevelName', 'atexit', 'basicConfig', 'cStringIO', 'codecs', 'critical', 'currentframe', 'debug', 'disable', 'error', 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass', 'info', 'log', 'logProcesses', 'logThreads', 'makeLogRecord', 'os', 'raiseExceptions', 'root', 'setLoggerClass', 'shutdown', 'string', 'sys', 'thread', 'threading', 'time', 'traceback', 'types', 'warn', 'warning']

正如我们所看到的,我们拥有相同的组件集。

请记住,这不是很干,这意味着您需要根据您所在的底层系统更新日志模块的位置,您可以通过以下方式检查它

>>> import logging
>>> logging.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.pyc'

或在找不到imp.find_module fp, pathname, description = imp.find_module('logging')您的自定义的目录中使用...logging.py

作为最后一点,我确定你有理由命名你的模块logging.py,我仍然会推荐其他不会冲突的东西。

于 2012-09-12T23:16:08.840 回答
1

来自 samy.vilar 的答案提供了许多有用的选项。但是,如果您正在寻找最简单、最直接的答案:

import imp
import sys

f, pathname, desc = imp.find_module('logging', sys.path[1:])
logging = imp.load_module('logging', f, pathname, desc)

这里有几点需要注意:

load_module调用更像reload(logging)import logging它不会logging在本地范围内绑定名称,而是会替换名称下的任何现有模块logging。所以,如果你在此之前做过一个import logging,那么这个名字现在指的是新模块,而不是旧模块;如果没有,则名称logging不会绑定在您的范围内。(这就是为什么在logging =上面,将其纳入范围。)

我不知道是否真的保证将当前目录放入模块路径的''实际上是sys.path. 就此而言,始终可以自己将“”或“.”插入到 sys.path 中。所以,如果你想变得偏执,你可以这样做:

f, pathname, desc = imp.find_module('logging', [path for path in sys.path if path and path[0] != '.'])

或者您可能会变得更加偏执,例如,比较并abspath(path)以各种方式确保没有人偷偷地强迫您重新导入自己。这取决于你的目标是什么。sys.argv[0]os.getcwd()

于 2012-09-12T23:40:17.910 回答
-1

导入的文件缓存在 中sys.modules,任何尝试导入另一个同名模块的尝试都只会返回缓存的模块。没有办法解决冲突。

作为一个黑客,你可以删除 中的字典条目sys.modules,但我不知道这会有多好。买者自负。

del sys.modules['logging']

当然,在那之后,您必须找到一种方法来修改路径,以便导入正确的文件。

我的总体建议是完全防止这种情况并重命名您的文件,以免发生冲突。

于 2012-09-12T22:04:29.820 回答