Reputation: 109
I know this is possible, because I've done it before. For various reasons, I no longer have access to the code where I did it before.
My code looks like this:
transformationsDirectory = os.path.join('..', 'transformations')
for transformationName in requestedTransformationNames.keys():
if os.path.isdir(os.path.join(transformationsDirectory, transformationName)):
sys.stdout.write('\t' + transformationName + '...\n')
sys.stdout.flush()
sys.path.append(os.path.join(transformationsDirectory, transformationName))
mainTransformationPythonModule = importlib.import_module('Transformation')
print(str(sys.path))
print(dir(mainTransformationPythonModule))
sys.path.remove(os.path.join(transformationsDirectory, transformationName))
There are two folders in the "transformations" directory getting imported, one called "stats" and one called "strings". Both contain a file called "Transformation.py" that contains a Transformation class.
The output from running the code:
['/Users/<working directory>', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python35.zip', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/plat-darwin', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload', '/Users/Eddie/Library/Python/3.5/lib/python/site-packages', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages', '../transformations/stats']
['AbstractTransformation', 'Output', 'Transformation', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'copy', 'os']
['/Users/<working directory>', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python35.zip', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/plat-darwin', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload', '/Users/Eddie/Library/Python/3.5/lib/python/site-packages', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages', '../transformations/strings']
['AbstractTransformation', 'Output', 'Transformation', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'copy', 'os']
So the output for the sys.path is correct, but the output for the loaded modules is not. They should not be the same (strings contains many more things than are listed), yet they are. From that and the behaviour of the rest of the program, it is clear that python is importing stats/Transformation.py twice instead of importing it once and strings/Transformation.py once. Why? stats isn't even in the sys.path when the second import occurs.
If I change the names of stats/Transformation.py and strings/Transformation.py to be distinct, it works. But I know it can work with them being the same (And for various reasons, I want them to be the same), yet it won't. Why?
Upvotes: 2
Views: 161
Reputation: 30210
This path juggling approach in your script is intense, try not to do it -- it will be incredibly difficult to debug, and forget trying to transfer it to new installs, a colleague, etc.
Instead try something like:
from common_dir.stats.transformations import Transformations as StatsTransformations
from common_dir.strings.transformations import Transformations as StringsTransformations
The from x import y
part will help you navigate into directories.
The import y as z
part will help you disambiguate classes with the same name.
Note: In some cases, and depending on your python version, you may need __init__.py
files in the folders you're descending into (they can be blank) -- it's good practice and you should probably do it regardless, but since 3.3 you'll only need them if they would shadow (have the same as) an already-installed package. (more info)
Upvotes: 3