Importing a file with the same name as the file you are in

Suppose you are in a file called logging.py. If you try to import a standard registration module, you will end up importing the file you are in. How can you import the standard logging module here?

+4
source share
4 answers

The answer from samy.vilar provides many useful options. But if you are looking for the simplest and most direct answer:

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

A few things to note here:

The load_module call load_module more like reload(logging) than import logging in that it will not bind the logging name in the local scope, but will replace any existing module called logging . So, if you did import logging before this, this name now refers to the new module, and not to the old; if you have not done so, the name logging not related in your area. (This is why logging = is higher to put it in the scope.)

I don’t know if this really ensured that ``, which places the current directory in the module path, is actually the first entry in sys.path . In this case, you can always insert '', or, for that matter, '.', In sys.path yourself. So, if you want to be paranoid, you can do something like this:

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

Or you could get even more paranoid, for example, compare abspath(path) with sys.argv[0] and os.getcwd() various ways to make sure no one is hiding that you are re-importing yourself. It depends on your goals.

+1
source

You can always delete the current directory from sys.path , but it is very hacky and unreliable. After testing, I realized that this can work if the file is executing (like __main__ , but not if it is imported, which is very unreliable).

I think the best thing you could do is not to name your file with the name used by the std lib package.

+2
source

Well, you can use imp to load the module with an absolute path.

 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. 

on my mac i did this:

 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'] 

as we see, we have the same many components.

Keep in mind that this is not very dry, which means that you will need to update the location of the registration module based on the base system you are in, you can check it on

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

or use imp.find_module fp, pathname, description = imp.find_module('logging') in the directory where your custom logging.py cannot be found ...

As a last note. We are sure that you have reasons for naming your module. logging.py I would recommend something else that does not conflict.

+1
source

Imported files are cached in sys.modules , and any attempt to import another module with the same name will simply return the cached module. Unable to resolve the conflict.

As a hack, you can delete the dictionary entry in sys.modules , but I don't know how well this works. Caveat Emptor.

 del sys.modules['logging'] 

Of course, after that you will need to find a way to change the path in order to import the correct file.

My general advice is to completely prevent the situation and rename the file so that there is no conflict.

-1
source

Source: https://habr.com/ru/post/1433903/


All Articles