How do I import a module given the full path?
For Python 3.5+ use (docs):
import importlib.util
import sys
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
sys.modules["module.name"] = foo
spec.loader.exec_module(foo)
foo.MyClass()
For Python 3.3 and 3.4 use:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Although this has been deprecated in Python 3.4.)
For Python 2 use:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
There are equivalent convenience functions for compiled Python files and DLLs.
See also http://bugs.python.org/issue21436.
How to import a module given the full path of the module in python 3.5?
try this (Python 3.5+ support this syntax):
import importlib.util
spec = importlib.util.spec_from_file_location("lib.test", "/test/lib/test.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
Python 3.4: How to import a module given the full path?
This should work for all python files, regardless of file extension:
import importlib.machinery
modulename = importlib.machinery.SourceFileLoader('modulename','/Path/To/module.py').load_module()
This method was mentioned in the deprecation message in the imp.load_module
documentation.
Python 3.5+: How to dynamically import a module given the full file path (in the presence of implicit sibling imports)?
The easiest solution I could come up with is to temporarily modify sys.path
in the function doing the import:
from contextlib import contextmanager
@contextmanager
def add_to_path(p):
import sys
old_path = sys.path
sys.path = sys.path[:]
sys.path.insert(0, p)
try:
yield
finally:
sys.path = old_path
def path_import(absolute_path):
'''implementation taken from https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly'''
with add_to_path(os.path.dirname(absolute_path)):
spec = importlib.util.spec_from_file_location(absolute_path, absolute_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
This should not cause any problems unless you do imports in another thread concurrently. Otherwise, since sys.path
is restored to its previous state, there should be no unwanted side effects.
Edit:
I realize that my answer is somewhat unsatisfactory but, digging into the code reveals that, the line spec.loader.exec_module(module)
basically results in exec(spec.loader.get_code(module.__name__),module.__dict__)
getting called. Here spec.loader.get_code(module.__name__)
is simply the code contained in lib.py.
Thus a better answer to the question would have to find a way to make the import
statement behave differently by simply injecting one or more global variables through the second argument of the exec-statement. However, "whatever you do to make the import machinery look in that file's folder, it'll have to linger beyond the duration of the initial import, since functions from that file might perform further imports when you call them", as stated by @user2357112 in the question comments.
Unfortunately the only way to change the behavior of the import
statement seems to be to change sys.path
or in a package __path__
. module.__dict__
already contains __path__
so that doesn't seem to work which leaves sys.path
(Or trying to figure out why exec does not treat the code as a package even though it has __path__
and __package__
... - But I don't know where to start - Maybe it has something to do with having no __init__.py
file).
Furthermore this issue does not seem to be specific to importlib
but rather a general problem with sibling imports.
Edit2: If you don't want the module to end up in sys.modules
the following should work (Note that any modules added to sys.modules
during the import are removed):
from contextlib import contextmanager
@contextmanager
def add_to_path(p):
import sys
old_path = sys.path
old_modules = sys.modules
sys.modules = old_modules.copy()
sys.path = sys.path[:]
sys.path.insert(0, p)
try:
yield
finally:
sys.path = old_path
sys.modules = old_modules
How to import function from a module given absolute path?
No, there is no such way.
That said...
from bar import foo
Is also importing the whole module bar
it is like:
import bar
foo = bar.foo
del globals['bar']
from module import * using full path in python
I think the easiest way is to add your full path to sys.path
:
import sys
sys.path.append('<path_to_folder_with_your_module>')
from mymodule import *
Python3 import module from sibling directory
I found out, that I could work with sys.path.append & os.path.abspath. So the solution is like this:
directory stucture:
Root
-- main.py
-- __init__.py
-- folder1
----- __init__.py
----- a.py
-- folder2
----- __init__.py
----- b.py
To use testFunction from folder1/a.py in folder2/b.py the code in b.py should be like this:
import sys
import os
sys.path.append(os.path.abspath('../Root/folder1'))
from a import testFunction
Related Topics
How to Make a Python Script Run Like a Service or Daemon in Linux
How to Get Monotonic Time Durations in Python
Change Default Python Version from 2.4 to 2.6
How to Make a Flat List Out of a List of Lists
How to Unnest (Explode) a Column in a Pandas Dataframe, into Multiple Rows
Syntax Error on Print With Python 3
How to Group Dataframe Rows into List in Pandas Groupby
Adding a Scrollbar to a Group of Widgets in Tkinter
How Does the @Property Decorator Work in Python
How to Unescape HTML Entities in a String in Python 3.1
Uninstall Python Built from Source
How to Use Export With Python on Linux
How to Split a List into Equally-Sized Chunks
How to Print Without a Newline or Space