导入与您所在文件同名的文件

时间:2012-09-12 21:59:18

标签: python import names

让我们说你在一个名为logging.py的文件中。如果您尝试导入标准日志记录模块,您最终将导入您所在的文件。如何从此处导入标准日志记录模块?

4 个答案:

答案 0 :(得分:2)

您可以随时从sys.path删除当前目录,但这非常hackish,而且不可靠。经过测试,我意识到这可以在文件运行时运行(如__main__,但如果它被导入则不行,这是非常不可靠的。)

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

答案 1 :(得分: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我还是会推荐一些不会发生冲突的东西。

答案 2 :(得分: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(),以确保没有人偷偷地强迫你重新导入自己。这取决于你的目标。

答案 3 :(得分:-1)

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

作为一个黑客,你可以删除sys.modules中的字典条目,但我不知道它会有多好用。警告Emptor。

del sys.modules['logging']

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

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