Find Python module filename - python

I got module name which contains declaration of os.path.isfile. Jedi lib gave me genericpath (without file path). Now i want to get full filename of PY file with this genericpath module. E.g. "C:\Py27\Lib\genericpath.py". How can I do it? Jedi cannot do it?

You could check the value of __file__:
>>> import genericpath
>>> genericpath.__file__
'/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/genericpath.pyc'

When __file__ doesn't work, do it the proper way—use inspect:
>>> import somemodule
>>> import inspect
>>> inspect.getfile(somemodule)
'/usr/lib64/python2.7/somemodule.pyc'

Like this:
>>> import re
>>> re.__file__
'/usr/lib/python2.7/re.pyc'
For packages that are not part of the Python core, you can also use __path__:
>>> import requests
>>> requests.__file__
'/usr/local/lib/python2.7/dist-packages/requests-1.1.0-py2.7.egg/requests/__init__.pyc'
>>> requests.__path__
['/usr/local/lib/python2.7/dist-packages/requests-1.1.0-py2.7.egg/requests']

Get module filename without loading it:
print(importlib.util.find_spec("urllib.request", None).origin)

Related

How to make Python imports dynamic? [duplicate]

How can I import an arbitrary python source file (whose filename could contain any characters, and does not always ends with .py) in Python 3.3+?
I used imp.load_module as follows:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
It still works in Python 3.3, but according to imp.load_module documentation, it is deprecated:
Deprecated since version 3.3: Unneeded as loaders should be used to
load modules and find_module() is deprecated.
and imp module documentation recommends to use importlib:
Note New programs should use importlib rather than this module.
What is the proper way to load an arbitrary python source file in Python 3.3+ without using the deprecated imp.load_module function?
Found a solution from importlib test code.
Using importlib.machinery.SourceFileLoader:
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
NOTE: only works in Python 3.3+.
UPDATE Loader.load_module is deprecated since Python 3.4. Use Loader.exec_module instead:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Updated for Python >= 3.8:
Short version:
>>> # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
>>> import importlib.util, sys
>>> spec = importlib.util.spec_from_file_location(modname, fname)
>>> module = importlib.util.module_from_spec(spec)
>>> sys.modules[modname] = module
>>> spec.loader.exec_module(module)
Full version:
>>> import importlib.util
>>> import sys
>>> from pathlib import Path
>>> from typing import TYPE_CHECKING
>>>
>>>
>>> if TYPE_CHECKING:
... import types
...
...
>>> def import_source_file(fname: str | Path, modname: str) -> "types.ModuleType":
... """
... Import a Python source file and return the loaded module.
... Args:
... fname: The full path to the source file. It may container characters like `.`
... or `-`.
... modname: The name for the loaded module. It may contain `.` and even characters
... that would normally not be allowed (e.g., `-`).
... Return:
... The imported module
... Raises:
... ImportError: If the file cannot be imported (e.g, if it's not a `.py` file or if
... it does not exist).
... Exception: Any exception that is raised while executing the module (e.g.,
... :exc:`SyntaxError). These are errors made by the author of the module!
... """
... # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
... spec = importlib.util.spec_from_file_location(modname, fname)
... if spec is None:
... raise ImportError(f"Could not load spec for module '{modname}' at: {fname}")
... module = importlib.util.module_from_spec(spec)
... sys.modules[modname] = module
... try:
... spec.loader.exec_module(module)
... except FileNotFoundError as e:
... raise ImportError(f"{e.strerror}: {fname}") from e
... return module
...
>>> import_source_file(Path("/tmp/my_mod.py"), "my_mod")
<module 'my_mod' from '/tmp/my_mod.py'>
Original answer for Python 3.5 and 3.6
Shorter version of #falsetru 's solution:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
I tested it with Python 3.5 and 3.6.
According to the comments, it does not work with arbitrary file extensions.
Similar to #falsetru but for Python 3.5+ and accounting for what the importlib doc states on using importlib.util.module_from_spec over types.ModuleType:
This function [importlib.util.module_from_spec] is preferred over using types.ModuleType to create a new
module as spec is used to set as many import-controlled attributes on
the module as possible.
We are able to import any file with importlib alone by modifying the importlib.machinery.SOURCE_SUFFIXES list.
import importlib
importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()
importlib helper function
Here is a convenient, ready-to-use helper to replace imp, with an example. The technique is the same as that of https://stackoverflow.com/a/19011259/895245 , this is just providing a more convenient function.
main.py
#!/usr/bin/env python3
import os
import importlib
def import_path(path):
module_name = os.path.basename(path).replace('-', '_')
spec = importlib.util.spec_from_loader(
module_name,
importlib.machinery.SourceFileLoader(module_name, path)
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[module_name] = module
return module
notmain = import_path('not-main')
print(notmain)
print(notmain.x)
not-main
x = 1
Run:
python3 main.py
Output:
<module 'not_main' from 'not-main'>
1
I replace - with _ because my importable Python executables without extension have hyphens as in my-cmd. This is not mandatory, but produces better module names like my_cmd.
This pattern is also mentioned in the docs at: https://docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly
I ended up moving to it because after updating to Python 3.7, import imp prints:
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
and I don't know how to turn that off, this was asked at:
The imp module is deprecated
How to ignore deprecation warnings in Python
Tested in Python 3.7.3.
after many failure solutions this one works for me
def _import(func,*args):
import os
from importlib import util
module_name = "my_module"
BASE_DIR = "wanted module directory path"
path = os.path.join(BASE_DIR,module_name)
spec = util.spec_from_file_location(func, path)
mod = util.module_from_spec(spec)
spec.loader.exec_module(mod)
return getattr(mod,func)(*args)
and to call it just write the function name and it's parameters _import("function",*args)

Dynamically import two files into another file in python which those two files are in the dufferent directories [duplicate]

How can I import an arbitrary python source file (whose filename could contain any characters, and does not always ends with .py) in Python 3.3+?
I used imp.load_module as follows:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
It still works in Python 3.3, but according to imp.load_module documentation, it is deprecated:
Deprecated since version 3.3: Unneeded as loaders should be used to
load modules and find_module() is deprecated.
and imp module documentation recommends to use importlib:
Note New programs should use importlib rather than this module.
What is the proper way to load an arbitrary python source file in Python 3.3+ without using the deprecated imp.load_module function?
Found a solution from importlib test code.
Using importlib.machinery.SourceFileLoader:
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
NOTE: only works in Python 3.3+.
UPDATE Loader.load_module is deprecated since Python 3.4. Use Loader.exec_module instead:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Updated for Python >= 3.8:
Short version:
>>> # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
>>> import importlib.util, sys
>>> spec = importlib.util.spec_from_file_location(modname, fname)
>>> module = importlib.util.module_from_spec(spec)
>>> sys.modules[modname] = module
>>> spec.loader.exec_module(module)
Full version:
>>> import importlib.util
>>> import sys
>>> from pathlib import Path
>>> from typing import TYPE_CHECKING
>>>
>>>
>>> if TYPE_CHECKING:
... import types
...
...
>>> def import_source_file(fname: str | Path, modname: str) -> "types.ModuleType":
... """
... Import a Python source file and return the loaded module.
... Args:
... fname: The full path to the source file. It may container characters like `.`
... or `-`.
... modname: The name for the loaded module. It may contain `.` and even characters
... that would normally not be allowed (e.g., `-`).
... Return:
... The imported module
... Raises:
... ImportError: If the file cannot be imported (e.g, if it's not a `.py` file or if
... it does not exist).
... Exception: Any exception that is raised while executing the module (e.g.,
... :exc:`SyntaxError). These are errors made by the author of the module!
... """
... # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
... spec = importlib.util.spec_from_file_location(modname, fname)
... if spec is None:
... raise ImportError(f"Could not load spec for module '{modname}' at: {fname}")
... module = importlib.util.module_from_spec(spec)
... sys.modules[modname] = module
... try:
... spec.loader.exec_module(module)
... except FileNotFoundError as e:
... raise ImportError(f"{e.strerror}: {fname}") from e
... return module
...
>>> import_source_file(Path("/tmp/my_mod.py"), "my_mod")
<module 'my_mod' from '/tmp/my_mod.py'>
Original answer for Python 3.5 and 3.6
Shorter version of #falsetru 's solution:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
I tested it with Python 3.5 and 3.6.
According to the comments, it does not work with arbitrary file extensions.
Similar to #falsetru but for Python 3.5+ and accounting for what the importlib doc states on using importlib.util.module_from_spec over types.ModuleType:
This function [importlib.util.module_from_spec] is preferred over using types.ModuleType to create a new
module as spec is used to set as many import-controlled attributes on
the module as possible.
We are able to import any file with importlib alone by modifying the importlib.machinery.SOURCE_SUFFIXES list.
import importlib
importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()
importlib helper function
Here is a convenient, ready-to-use helper to replace imp, with an example. The technique is the same as that of https://stackoverflow.com/a/19011259/895245 , this is just providing a more convenient function.
main.py
#!/usr/bin/env python3
import os
import importlib
def import_path(path):
module_name = os.path.basename(path).replace('-', '_')
spec = importlib.util.spec_from_loader(
module_name,
importlib.machinery.SourceFileLoader(module_name, path)
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[module_name] = module
return module
notmain = import_path('not-main')
print(notmain)
print(notmain.x)
not-main
x = 1
Run:
python3 main.py
Output:
<module 'not_main' from 'not-main'>
1
I replace - with _ because my importable Python executables without extension have hyphens as in my-cmd. This is not mandatory, but produces better module names like my_cmd.
This pattern is also mentioned in the docs at: https://docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly
I ended up moving to it because after updating to Python 3.7, import imp prints:
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
and I don't know how to turn that off, this was asked at:
The imp module is deprecated
How to ignore deprecation warnings in Python
Tested in Python 3.7.3.
after many failure solutions this one works for me
def _import(func,*args):
import os
from importlib import util
module_name = "my_module"
BASE_DIR = "wanted module directory path"
path = os.path.join(BASE_DIR,module_name)
spec = util.spec_from_file_location(func, path)
mod = util.module_from_spec(spec)
spec.loader.exec_module(mod)
return getattr(mod,func)(*args)
and to call it just write the function name and it's parameters _import("function",*args)

How to check if a module/library/package is part of the python standard library?

I have installed sooo many libraries/modules/packages with pip and now I cannot differentiate which is native to the python standard library and which is not. This causes problem when my code works on my machine but it doesn't work anywhere else.
How can I check if a module/library/package that I import in my code is from the python stdlib?
Assume that the checking is done on the machine with all the external libraries/modules/packages, otherwise I could simply do a try-except import on the other machine that doesn't have them.
For example, I am sure these imports work on my machine, but when it's on a machine with only a plain Python install, it breaks:
from bs4 import BeautifulSoup
import nltk
import PIL
import gensim
You'd have to check all modules that have been imported to see if any of these are located outside of the standard library.
The following script is not bulletproof but should give you a starting point:
import sys
import os
external = set()
exempt = set()
paths = (os.path.abspath(p) for p in sys.path)
stdlib = {p for p in paths
if p.startswith((sys.prefix, sys.real_prefix))
and 'site-packages' not in p}
for name, module in sorted(sys.modules.items()):
if not module or name in sys.builtin_module_names or not hasattr(module, '__file__'):
# an import sentinel, built-in module or not a real module, really
exempt.add(name)
continue
fname = module.__file__
if fname.endswith(('__init__.py', '__init__.pyc', '__init__.pyo')):
fname = os.path.dirname(fname)
if os.path.dirname(fname) in stdlib:
# stdlib path, skip
exempt.add(name)
continue
parts = name.split('.')
for i, part in enumerate(parts):
partial = '.'.join(parts[:i] + [part])
if partial in external or partial in exempt:
# already listed or exempted
break
if partial in sys.modules and sys.modules[partial]:
# just list the parent name and be done with it
external.add(partial)
break
for name in external:
print name, sys.modules[name].__file__
Put this is a new module, import it after all imports in your script, and it'll print all modules that it thinks are not part of the standard library.
The standard library is defined in the documentation of python. You can just search there, or put the module names into a list and check programmatically with that.
Alternatively, in python3.4 there's a new isolated mode that allows to ignore a certain number of user-defined library paths. In previous versions of python you can use -s to ignore the per-user environment and -E to ignore the system defined variables.
In python2 a very simple way to check if a module is part of the standard library is to clear the sys.path:
>>> import sys
>>> sys.path = []
>>> import numpy
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named numpy
>>> import traceback
>>> import os
>>> import re
However this doesn't work in python3.3+:
>>> import sys
>>> sys.path = []
>>> import traceback
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'traceback'
[...]
This is because starting with python3.3 the import machinery was changed, and importing the standard library uses the same mechanism as importing any other module (see the documentation).
In python3.3 the only way to make sure that only stdlib's imports succeed is to add only the standard library path to sys.path, for example:
>>> import os, sys, traceback
>>> lib_path = os.path.dirname(traceback.__file__)
>>> sys.path = [lib_path]
>>> import traceback
>>> import re
>>> import numpy
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'numpy'
I used the traceback module to get the library path, since this should work on any system.
For the built-in modules, which are a subset of the stdlib modules, you can check sys.builtin_module_names
#Bakuriu's answer was very useful to me. The only problem I experienced is if you want to check if a particular module is stdlib however is has been imported already. In that case, sys.modules will only have an entry for it so even if sys.path is stripped, the import will succeed:
In [1]: import sys
In [2]: import virtualenv
In [3]: sys.path = []
In [4]: try:
__import__('virtualenv')
except ImportError:
print(False)
else:
print(True)
...:
True
vs
In [1]: import sys
In [2]: sys.path = []
In [3]: try:
__import__('virtualenv')
except ImportError:
print(False)
else:
print(True)
...:
False
I whipped out the following solution which seems to work in both Python2 and Python3:
from __future__ import unicode_literals, print_function
import sys
from contextlib import contextmanager
from importlib import import_module
#contextmanager
def ignore_site_packages_paths():
paths = sys.path
# remove all third-party paths
# so that only stdlib imports will succeed
sys.path = list(filter(
None,
filter(lambda i: 'site-packages' not in i, sys.path)
))
yield
sys.path = paths
def is_std_lib(module):
if module in sys.builtin_module_names:
return True
with ignore_site_packages_paths():
imported_module = sys.modules.pop(module, None)
try:
import_module(module)
except ImportError:
return False
else:
return True
finally:
if imported_module:
sys.modules[module] = imported_module
You can keep track of the source code here

Import arbitrary python source file. (Python 3.3+)

How can I import an arbitrary python source file (whose filename could contain any characters, and does not always ends with .py) in Python 3.3+?
I used imp.load_module as follows:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
It still works in Python 3.3, but according to imp.load_module documentation, it is deprecated:
Deprecated since version 3.3: Unneeded as loaders should be used to
load modules and find_module() is deprecated.
and imp module documentation recommends to use importlib:
Note New programs should use importlib rather than this module.
What is the proper way to load an arbitrary python source file in Python 3.3+ without using the deprecated imp.load_module function?
Found a solution from importlib test code.
Using importlib.machinery.SourceFileLoader:
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
NOTE: only works in Python 3.3+.
UPDATE Loader.load_module is deprecated since Python 3.4. Use Loader.exec_module instead:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Updated for Python >= 3.8:
Short version:
>>> # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
>>> import importlib.util, sys
>>> spec = importlib.util.spec_from_file_location(modname, fname)
>>> module = importlib.util.module_from_spec(spec)
>>> sys.modules[modname] = module
>>> spec.loader.exec_module(module)
Full version:
>>> import importlib.util
>>> import sys
>>> from pathlib import Path
>>> from typing import TYPE_CHECKING
>>>
>>>
>>> if TYPE_CHECKING:
... import types
...
...
>>> def import_source_file(fname: str | Path, modname: str) -> "types.ModuleType":
... """
... Import a Python source file and return the loaded module.
... Args:
... fname: The full path to the source file. It may container characters like `.`
... or `-`.
... modname: The name for the loaded module. It may contain `.` and even characters
... that would normally not be allowed (e.g., `-`).
... Return:
... The imported module
... Raises:
... ImportError: If the file cannot be imported (e.g, if it's not a `.py` file or if
... it does not exist).
... Exception: Any exception that is raised while executing the module (e.g.,
... :exc:`SyntaxError). These are errors made by the author of the module!
... """
... # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
... spec = importlib.util.spec_from_file_location(modname, fname)
... if spec is None:
... raise ImportError(f"Could not load spec for module '{modname}' at: {fname}")
... module = importlib.util.module_from_spec(spec)
... sys.modules[modname] = module
... try:
... spec.loader.exec_module(module)
... except FileNotFoundError as e:
... raise ImportError(f"{e.strerror}: {fname}") from e
... return module
...
>>> import_source_file(Path("/tmp/my_mod.py"), "my_mod")
<module 'my_mod' from '/tmp/my_mod.py'>
Original answer for Python 3.5 and 3.6
Shorter version of #falsetru 's solution:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
I tested it with Python 3.5 and 3.6.
According to the comments, it does not work with arbitrary file extensions.
Similar to #falsetru but for Python 3.5+ and accounting for what the importlib doc states on using importlib.util.module_from_spec over types.ModuleType:
This function [importlib.util.module_from_spec] is preferred over using types.ModuleType to create a new
module as spec is used to set as many import-controlled attributes on
the module as possible.
We are able to import any file with importlib alone by modifying the importlib.machinery.SOURCE_SUFFIXES list.
import importlib
importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()
importlib helper function
Here is a convenient, ready-to-use helper to replace imp, with an example. The technique is the same as that of https://stackoverflow.com/a/19011259/895245 , this is just providing a more convenient function.
main.py
#!/usr/bin/env python3
import os
import importlib
def import_path(path):
module_name = os.path.basename(path).replace('-', '_')
spec = importlib.util.spec_from_loader(
module_name,
importlib.machinery.SourceFileLoader(module_name, path)
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[module_name] = module
return module
notmain = import_path('not-main')
print(notmain)
print(notmain.x)
not-main
x = 1
Run:
python3 main.py
Output:
<module 'not_main' from 'not-main'>
1
I replace - with _ because my importable Python executables without extension have hyphens as in my-cmd. This is not mandatory, but produces better module names like my_cmd.
This pattern is also mentioned in the docs at: https://docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly
I ended up moving to it because after updating to Python 3.7, import imp prints:
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
and I don't know how to turn that off, this was asked at:
The imp module is deprecated
How to ignore deprecation warnings in Python
Tested in Python 3.7.3.
after many failure solutions this one works for me
def _import(func,*args):
import os
from importlib import util
module_name = "my_module"
BASE_DIR = "wanted module directory path"
path = os.path.join(BASE_DIR,module_name)
spec = util.spec_from_file_location(func, path)
mod = util.module_from_spec(spec)
spec.loader.exec_module(mod)
return getattr(mod,func)(*args)
and to call it just write the function name and it's parameters _import("function",*args)

Find path of module without importing in Python

I've seen several approaches for finding the path of a module by first importing it. Is there a way to do this without importing the module?
Using pkgutil module:
>>> import pkgutil
>>> package = pkgutil.get_loader("pip")
>>> package.filename
'/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip'
>>> package = pkgutil.get_loader("threading")
>>> package.filename
'/usr/lib/python2.6/threading.py'
>>> package = pkgutil.get_loader("sqlalchemy.orm")
>>> package.filename
'/usr/lib/pymodules/python2.6/sqlalchemy/orm'
In Python 3, use pkgutil.get_loader("module name").get_filename() instead.
Using imp module:
>>> import imp
>>> imp.find_module('sqlalchemy')
(None, '/usr/lib/pymodules/python2.6/sqlalchemy', ('', '', 5))
>>> imp.find_module('pip')
(None, '/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip', ('', '', 5))
>>> imp.find_module('threading')
(<open file '/usr/lib/python2.6/threading.py', mode 'U' at 0x7fb708573db0>, '/usr/lib/python2.6/threading.py', ('.py', 'U', 1))
N.B: with imp module you can't do something like imp.find_module('sqlalchmy.orm')
For python3 imp is deprecated. Use pkgutil (as seen above) or for Python 3.4+ use importlib.util.find_spec:
>>> import importlib
>>> spec = importlib.util.find_spec("threading")
>>> spec.origin
'/usr/lib64/python3.6/threading.py'
You might want to try running this in your interpreter:
>>> import sys
>>> sys.modules['codecs'].__file__ # codecs is just an example
'/usr/lib/python2.7/codecs.pyc'

Categories

Resources