Given a path to a file, I need the package name to pass to importlib.import_module()
so that relative imports will work correctly. I can't import it and then check module.__package__
because it won't import successfully.
Asked
Active
Viewed 180 times
2
-
Can you add what you have tried to far including your folder / file structure? – Klaus D. Apr 23 '15 at 14:48
2 Answers
2
Here's one rather generic method:
import pathlib
import sys
def get_module_name(path):
f = pathlib.Path(path).resolve()
for i in map(pathlib.Path, sys.path):
try:
f.relative_to(i)
except ValueError:
pass
else:
*parts, fname = f.relative_to(i).parts
return ".".join(parts), [f.stem]
module, fromlist = get_module_name("Programming/Python/kernprof.py")
print(module, fromlist)
imported_module = __import__(module, fromlist=fromlist)
print(imported_module)
print(getattr(imported_module, fromlist[0]))
Outputs:
Programming.Python ['kernprof']
<module 'Programming.Python' (namespace)>
<module 'Programming.Python.kernprof' from '/home/matthew/Programming/Python/kernprof.py'>
This solution can handle import with any path from sys.path
, but cannot do relative imports (imports above the sys.path
). For the how __import__
is used, see Why does Python's __import__ require fromlist?.
-
This method has some limitations because it makes a static determination using the directory structure without processing __init__.py files or other ways to monkey with deciding which files belong to which package, but it's good enough for my purposes. – ceridwen Apr 28 '15 at 17:32
-
Yeah, processing `__init__`s and co would be pretty complicated, with some possibly unwanted results. – matsjoyce Apr 29 '15 at 15:51
0
What about this helper ?
import os
def get_parent_package(path):
parent_path = os.path.split(path)[0]
while parent_path != os.sep:
if '__init__.py' in os.listdir(parent_path):
return os.path.basename(parent_path)
parent_path = os.path.split(parent_path)[0]
return None
parent_path != os.sep must be improved if you are under windows.

Ali SAID OMAR
- 6,404
- 8
- 39
- 56
-
The major problem with this, as I discovered, is that in Python 3.3+ __init__.py is no longer needed to define a module, see Nick Coghlan's discussion at http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html. There can be other problems with traversing the directory tree from the bottom up for packages containing subpackages. – ceridwen Apr 28 '15 at 17:29