Reputation: 19561
Lets say you're in a file called logging.py. If you try to import the standard logging module, you'll end up importing the file you're in. How can you import the standard logging module from here?
Upvotes: 4
Views: 741
Reputation: 365697
The answer from samy.vilar gives lots of useful options. But if you're 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 is more like reload(logging)
than import logging
in that it won't bind the name logging
in the local scope, but will replace any existing module under the name logging
. So, if you've done an import logging
before this, that name now refers to the new module, not the old one; if you hadn't, the name logging
isn't bound in your scope. (That's why the logging =
is there above, to put it into scope.)
I don't know if it's actually guaranteed that the '' that puts the current directory into the module path is actually the first entry in sys.path
. For that matter, it's always possible to insert '', or for that matter '.', into sys.path yourself. So, if you want to be paranoid you could 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, e.g., compare abspath(path)
to sys.argv[0]
and os.getcwd()
in various ways to make sure nobody is sneakily forcing you to re-import yourself. It depends on what your goals are.
Upvotes: 1
Reputation: 11120
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 can see we have the same the set of components.
keep in mind that this isn't very dry, meaning you would need to update the location of the logging module based on the underlying system you are in, you can check for it by
>>> 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 a directory where your custom logging.py
can't be found ...
As a last note Im sure you have your reasons for naming your module logging.py
I would still recommend something else that wouldn't conflict.
Upvotes: 1
Reputation: 55207
You could always remove the current directory from sys.path
, but that's very hackish, and not reliable. After testing, I realized that this can works if the file is being run (as __main__
, but not if it's being imported, which is very unreliable).
I think the best thing you could do is not name your file with a name that is used by a std lib package.
Upvotes: 2
Reputation: 308130
Imported files are cached in sys.modules
, and any attempt to import another module with the same name will simply return the cached module. There's no way to resolve the conflict.
As a hack you could delete the dictionary entry in sys.modules
, but I don't know how well that would work. Caveat Emptor.
del sys.modules['logging']
Of course after that you'll have to find a way to modify the path so that the proper file gets imported.
My overall advice is to prevent the situation altogether and rename your file so that there's no conflict.
Upvotes: -1