Search code examples
pythonimportpython-module

Python problem importing my files in script (not in the Console)


i know that the problem I'm asking for have thousand of questions and answers, but i need an explanation for my spcific problem because is my first time using code written by others and I'm really confused about imports. So: I'm usin Pycharm and I pulled all the code (organized in directories) directly from a gitLab repo.

this is the structure :

C:\users\marco\PycharmProjects\Avv
└──ads-ai
     └──src
         └──dataElab
             └──dataprep.py
             └──datamod.py
         ├──doc2vec
         ├──logger
              └──log_setup.py
         ├──res
         ├──mod1.py
         ├──mod2.py
         ├──mod3.py
         └──rest
              └──api.py

my starting script is api.py , and I need to import mod1.py in there-

but start writing

import mod1

gives me an error.

the problem also is that on mod1, there are others import:

from logger import log_setup
from dataElab import dataprep, datamod

all imports give me the error 'NoModuleFound'. I tried: -add the path with sys.path.append - relative paths (from .. import mod1) but gives me ValueError: attempted realtive import beyond top-level package -absolute path

but nothing, i have always the "no module" error, for mod1 or for log_setup.

I want to use the script of Pycharm, not the Python Console. If I check with os.getwd() --> C:\users\marco\PycharmProjects\Avv\ads-ai\src\rest (should be correct).

and with sys.path --->

['C:\Users\marco.onnis\PycharmProjects\Avvocatura2020\ads-ai\src\restAPI', 'C:\Users\marco.onnis\PycharmProjects\Avvocatura2020', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020\python36.zip', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020\DLLs', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020\lib', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020\lib\site-packages', 'C:\Users\marco.onnis\AppData\Local\Continuum\anaconda3\envs\Avvocatura2020\lib\site-packages\xlsxwriter-1.2.8-py3.6.egg']

I'm so sorry if I'm asking again this type of questions, but I've problem understanding the concept of name , main and all that stuf, and I don't know what to do in my specific case ( I hope then to understand in general the topic)

thanks a lot!


Solution

  • The first thing I'd say to simplify this and help your understanding is to have a main.py in the root directory.

    C:\users\marco\PycharmProjects\Avv
    └──ads-ai
     └──main.py  # main script to run your code
     └──src
         └──dataElab
             └──dataprep.py
             └──datamod.py
         ├──doc2vec
         ├──logger
              └──log_setup.py
         ├──res
         ├──mod1.py
         ├──mod2.py
         ├──mod3.py
         └──rest
              └──api.py
    

    There are two methods to importing here, using __init__.py files or relative imports. An examle of a relative import would be like the below where you reference the directory (or subdirectories using dot notation)

    main.py

    from src import mod1  # imports mod1.py from '/src' folder
    from src.rest import api  # imports api.py from '/src/rest' folder
    

    The second way which works around using from x import y would be to put an empty __init__.py file in each of your directories

    C:\users\marco\PycharmProjects\Avv
    └──ads-ai
     └──main.py
     └──src
         └──__init__.py
         └──dataElab
             └──__init__.py
             └──dataprep.py
             └──datamod.py
         ├──doc2vec
         ├──logger
              └──__init__.py
              └──log_setup.py
         ├──res
         ├──mod1.py
         ├──mod2.py
         ├──mod3.py
         └──rest
              └──__init__.py
              └──api.py
    

    You can then import like this

    main.py

    import mod1  # imports mod1.py
    import api # imports api.py
    

    You could therefore have the following

    main.py

    import api
    

    api.py

    import mod1
    

    You should be vary when importing from different locations as you could end up with name conflicts for the modules if they share the same file name, just in different directories. In these cases you should also add as to deal modules having the same name

    e.g.

    main.py

    from src import mod1 as mod_one
    from src.rest import mod1 as mod_1