1

I'm new to Python, and I try to structure my Python application.
Given the following directory structure:

app  
 ┣ lexer  
 ┃ ┣ token  
 ┃ ┃ ┣ token.py  
 ┃ ┃ ┣ type.py  
 ┃ ┃ ┗ __init__.py  
 ┃ ┗ __init__.py  
 ┣ test  
 ┃ ┣ lexer  
 ┃ ┃ ┣ token   
 ┃ ┃ ┃ ┣ test_token.py  
 ┃ ┃ ┃ ┗ __init__.py  
 ┃ ┃ ┗ __init__.py   
 ┃ ┣ test_app.py  
 ┃ ┗ __init__.py   
 ┗ app.py  

Right now, the application is executed using the following command:

pyhton -m app

When I try to execute the application using

python -m .\app.py

The following error is raised:

Relative module names not supported.

Unit tests are being executed using:

python -m unittest

This works fine and without issues. Now, I'm trying to use the import the token / type.py file in the app.py file.

The contents of this file are:

from enum import Enum, unique

@unique
class Type(Enum):
    UNKNOWN = 1
    EOF     = 2

The following import statement is added in the app.py file:

from app.lexer.token.type import Type

Running the application right now yields the following error:

Traceback (most recent call last):
  File "C:\Python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\DEV\DEMO.ONE\app\app.py", line 17, in <module>
    from app.lexer.token.type import Type
  File "C:\DEV\DEMO.ONE\app\app.py", line 17, in <module>
   from app.lexer.token.type import Type
ModuleNotFoundError: No module named 'app.lexer'; 'app' is not a package

Any ideas on how this can be fixed?

Complexity
  • 5,682
  • 6
  • 41
  • 84

4 Answers4

1

app is not a package. A "directory" becomes a package by adding __init__.py in. Try adding app/__init__.py.

On a side note, type is a built-in class in python. It is a bad idea to name your module type.py. Rename it now or you will regret later.

Andreas Kraft
  • 3,754
  • 1
  • 30
  • 39
Petr Blahos
  • 2,253
  • 1
  • 11
  • 14
1

app/ itself isn't a package -since it doesn't include a __init__ file-. app/ is root of the application, while the package's path starts with lexer. So, change

from app.lexer.token.type import Type

to

from lexer.token.type import Type
rhytonix
  • 968
  • 6
  • 14
  • That does work, hower VS Code does NOT resolve the 'import'statement'. Any idea zhy? – Complexity Apr 23 '20 at 05:36
  • I'm not sure what you mean by 'resolve the import statement'. Can you update the original question with an image or the body of the new error. If you mean vscode is showing a squiggly line under the import statement, but the code is running fine when you use the `python` command, then you'll probably need to restart vscode. – rhytonix Apr 23 '20 at 05:52
  • That is exact what I mean, code is running fine. Restarting VS Code does not bring a solution ... NOTE: VS Code runs from the parent of the 'app/' directory. – Complexity Apr 23 '20 at 05:58
  • Unfortunately, I can't replicate this problem, but it's probably an env issue. Try updating the python extension, or create a new application folder (outside of app) with a dummy test file and check if vscode marks the imports there with a red line as well or not, and if it doesn't, then copy the contents over to the new folder. Also, check the following two posts [1](https://stackoverflow.com/questions/53939751/pylint-unresolved-import-error-in-visual-studio-code), [2](https://stackoverflow.com/questions/53939751/pylint-unresolved-import-error-in-visual-studio-code) for potential solutions. – rhytonix Apr 23 '20 at 06:24
  • The problem is that the python source code is not in the folder that's opened in VS Code but in a SUB folder. If I open that SUB folder directly, the import statements are recognized ... – Complexity Apr 23 '20 at 07:05
  • Why do you need to open vscode in a folder other than `app/`? My understanding from the image was that `app/` was the root folder, so naturally I would expect you would open vscode there. – rhytonix Apr 23 '20 at 07:31
  • The repo doesn't only contain a Python application, but some other stuff as well. I want to see everything in the VS Code application. – Complexity Apr 23 '20 at 08:04
  • I created a VENV using 'python -m venv .venv'. This seems to do the trick. – Complexity Apr 23 '20 at 08:26
  • Good to hear you found a solution! And thanks for adding it here. – rhytonix Apr 23 '20 at 08:40
0

i think you need to set environment variable PYTHONPATH before you execute the script from your project root folder.

in command line at your project root folder, do:

export PYTHONPATH=$(pwd)

or put the above in a .env file at project root folder and do

source .env

before executing your script

lingxiao
  • 1,214
  • 17
  • 33
0

Actually, python does not know about your app package. When you run python -m app it accedentally works because you have (I presume) started it in the app directory. Therefore python tries to look it up in current directory as well. But then you try to import app.something, and that does not work. Try importing just lexer.token.type. If that works, we know we are on the right track.

Then try

touch __init__.py
cd ..
python -m app.app

Now, to tell python about the package, you will have to make a setup.py file and then install it by doing

pip install -e .

That will put a link into python's library's site-packages directory and python will know about it. Once you have done it, you will be able to run python -m app.app from anywhere.

You might want to read about distutils: https://docs.python.org/3/distutils/setupscript.html

or python packaging: https://packaging.python.org/tutorials/packaging-projects/

Petr Blahos
  • 2,253
  • 1
  • 11
  • 14