1

How do I import a module and use it as if I installed it without actually installing it? More specifically, when I do imports on an installed module, all the imports are relative to the module. However when I just import it, all the imports are relative to the module it is called from.

As a specific example, in the below I would like run_import.py to print module not parent. But because it imports cfg from the parent not the module, it prints the wrong one. I would like to be able to run module1 on a standalone basis and have it isolated from any code that is calling it, much like you would in an installed package.

Directory structure is


module1/
  __init__.py
  cfg.py
  tasks.py
  run_module.py
  utils.py
cfg.py  
run_import.py
utils.py

Code


# cfg.py
level = 'parent'

# module1/cfg.py
level='module'

# module1/tasks.py

import cfg

def run_it():
    print(cfg.level)

# module1/run_module.py

import tasks

tasks.run_it() # prints 'module'

# module1/utils.py

def util_fun():
    print('util module')

# utils.py

def util_fun():
    print('util parent')

# run_import.py

import module1.tasks as tasks

tasks.run_it() # prints 'parent', would like it to print 'module'

import utils
utils.util_fun() # prints util parent, should not print util module


This give me what I was looking for but has the unintended consequence that everything gets imported relative to that module

import sys
sys.path.insert(0, "module1")

tasks.run_it() # prints 'parent'

import utils
utils.util_fun() # prints util module, not util parent

Here are a couple of answers I have looked it, they didn't seem to solve it.

What's the purpose of the "__package__" attribute in Python? this sounds like what is needed but not sure how that can be set

Python3 importlib.util.spec_from_file_location with relative path? look potentially promising but i'm not sure how to use it, particularly not sure what the file path should be

How to use a packed python package without installing it

Import a module from a relative path

Can a python module be imported without installing

Import module using relative paths

citynorman
  • 4,918
  • 3
  • 38
  • 39

2 Answers2

0

When you execute run_import.py, the imports are searching in the root folder (module1/).

So you can try changing module1/tasks.py

from module1 import cfg

def run_it():
    print(cfg.level)
Be Chiller Too
  • 2,502
  • 2
  • 16
  • 42
  • Yes that would work but I would like to be able to run `module1` on a standalone basis and have it isolated from any code that is calling it, much like you would in an installed package. – citynorman May 28 '21 at 16:47
  • Well it's a known problem in the python world, if you run a python file, it can not import modules above itself. A work-around is to keep all the main/executable files at the top-level of your project, and create subfolders for utils/test files. See here: https://www.patricksoftwareblog.com/structure-of-a-python-project/ – Be Chiller Too May 28 '21 at 18:50
0

Try this, adding the module to the path works if you would only like to change run_import.py

import sys
sys.path.insert(0, "module1")

from module1 import tasks
tasks.run_it()

Vikram Cothur
  • 11
  • 1
  • 3
  • This works but has the unintended consequence that everything gets imported relative to that module now, see updated question – citynorman Jun 05 '21 at 20:23