0

I have a solution with different folders and I wanted to create a common package for them to share reusable code. There are lot of examples for python packages are there. None of them addresses separate folder scenario in a simple way.

My folder structure is :

Client/
    __init__.py
    --logic.py
Common/
    __init__.py
    -- Constants.py
Server/
    __init__.py
    -- Test.py

My Test.py looks like this :

from Common import Constant        
print(Constant.TEST_VALUE)  #-- From common package

But the code not even passes the import statements.

Exception has occurred: ModuleNotFoundError No module named 'Common'

If I try with relative path : from ..Common import Constant

Error:

Exception has occurred: ImportError attempted relative import with no known parent package

My purpose is to reuse the constant.py file for both Cars and Server solution. There are examples for sys.path which I am not sure if its a good practice. Also the code in Common will not be having complex codes to proceed with installing them.

ACB
  • 121
  • 1
  • 9
  • "I would like to use the `Common` module and `Cars` module in `Test.py`" - those aren't modules; they're packages. "None of them addresses separate folder scenario in a simple way." Right; normally a project has a single top-level package. The simple solution is to just make one that encloses your other three folders, and then follow the usual advice. If you really do want separate packages that interact with each other, then the simplest approach is to *install* them (ideally in a virtual environment). – Karl Knechtel Feb 02 '22 at 16:56
  • "OR `PATH` is used to specify the path to module." I think you mean `PYTHONPATH`. I generally recommend against this. – Karl Knechtel Feb 02 '22 at 16:56
  • Does [my general answer here to a different importing-related question](https://stackoverflow.com/questions/70948736/classes-importing-other-classes-errors/70949290#70949290) happen to resolve the issue for you? – Karl Knechtel Feb 02 '22 at 16:58
  • @Karl In my case this is like a client-server arch,. One solution will be Cars+Common and another is Server+Common. I am from .NET background, that is why these mistakes. – ACB Feb 02 '22 at 17:06
  • 1
    Aha, so some users would specifically want two but not all three packages? Then I suppose you really do have three projects in your solution (in VS-speak), where Cars and Server both depend on Common. Best treat them as separate packages, and thus use absolute imports between them. – Karl Knechtel Feb 02 '22 at 17:11
  • Thanks @KarlKnechtel , I think you got my point. I believe you mean to use `sys.path` to common inside `Client` (changed from Cars to understand better) and `Server`? – ACB Feb 02 '22 at 17:34
  • I mean, when you set them up for installation, mark the dependencies; then install them all locally for testing. If done right, when other users later try to install `Cars` or `Server` (perhaps from PyPI or from GitHub), `pip` (or another installation tool) will automatically grab `Common` as well and install it in the appropriate way. – Karl Knechtel Feb 02 '22 at 17:38

2 Answers2

1

If these packages are meant to be part of the same conceptual project, then simply make a containing package. Now the relative import will work as long as you start from outside the package hierarchy, and ensure the containing folder is on sys.path. The easy ways to do that are to install the package (preferably to a virtual environment), or start python from that folder (in which case Cars, Common and Server appear as separate packages) or just outside (in which case the containing folder is a package and Cars, Common and Server are sub-packages - which is probably what you want; it's more consistent with how you will most likely install the code later).

If these packages are separate projects that happen to depend upon one another, then Python has no reason by default to look in any particular place for the dependency packages - aside from the places it ordinarily looks for anything. So, again, you can start python from the containing folder if there actually is such a containing folder; but there isn't a good project-organization reason for there to be a containing folder - so set up an actual project for each package, and install them all to the same virtual environment. Now you can do cross-package imports with absolute syntax (but not relative syntax, because that only works within a package hierarchy).

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • I assume that in the previous research you mention, you saw how to set up packages for installation, and install them. If not, [this](https://packaging.python.org/en/latest/) is the authoritative reference, straight from python.org. – Karl Knechtel Feb 02 '22 at 17:12
0

You can use this code found here:

# Test.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/Cars/')
sys.path.insert(1, '/path/to/Common/')

import Audi
import Constants
oflint_
  • 297
  • 1
  • 8