0

I want to import modules from subfolers in Python. It works from main.py to the subfolder, but not from subfolder to subfolder. Every folder has a __init__.py

This is how the folder structure looks like: Folder structure

I've created a little "class diagram", to show how it needs to be imported: Class diagram

main.py:

#! /usr/bin/env python

import os
from dotenv import load_dotenv
from os import path
from parser.Nfdump import Nfdump

def main():
    load_dotenv()
    
    p = Nfdump(os.getenv('flow_file_location'))
    p.Parse()

if __name__ == "__main__":
    main()

Nfdump.py

#! /usr/bin/env python

from types.Flow import Flow
from typing import NamedTuple
import ipaddress


class Nfdump:
    def __init__(self, file_location):
        self.file_location = file_location

    def Parse(self):
        ##parsing magic

Flow.py:

#! /usr/bin/env python
from typing import NamedTuple
import ipaddress

class Flow(NamedTuple):
    ip_source: ipaddress.ip_address
    port_source: int
    ip_dest: ipaddress.ip_address
    port_dest: int
    flags: str

Error thrown:

ModuleNotFoundError: No module named 'types.Flow'; 'types' is not a package

I am using Python 3 (3.10.2)

Marvin
  • 33
  • 7

2 Answers2

1

I think you should use relative imports. If I'm reading your hierarchy correctly, maybe the following:

In main:

from .parser.Nfdump import Nfdump

In Nfdump:

from ..types.Flow import Flow

The single dot means "one on the same level in the module hierarchy" and double dot means "one level up".

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Dronir
  • 866
  • 7
  • 10
  • If I use double dots, it complains I am outside the project folder. When using a single dot, it gave the same error (because of types is a Python thing) – Marvin Mar 03 '22 at 10:01
  • Do you have an `__init__.py` on the level of `main.py` as well? – Dronir Mar 03 '22 at 10:24
0

The reason for this error is that types is already a name used by Python for the standard library.

Rename your folder from types to something else.

https://docs.python.org/3/library/types.html


In addition, you will probably have to change your imports to contain the full path, and execute it inside of the folder containing flowscanner

from flowscanner.types.Flow import Flow
xjcl
  • 12,848
  • 6
  • 67
  • 89
  • This will not fix the problem. The path needed to find the project-specific module will not be searched, so renaming will not avoid a conflict - there is no conflict. By default, the standard library paths will appear *after* any project-specific paths in `sys.path`; thus, if a standard library module is being accidentally imported, the intended module would still not be imported otherwise (since its search path would shadow the standard library). – Karl Knechtel Mar 03 '22 at 09:46
  • Absolute imports can be used to solve the problem, but in this case the renaming will be irrelevant - since the project-specific module is now appropriately namespaced anyway. Better is to use relative imports. – Karl Knechtel Mar 03 '22 at 09:48
  • 1
    This has fixed the problem. It was indeed the 'types' naming. I was thinking of that too, but I didn't change it before :( Stupid. I've indeed tried relative imports too, but they also didn't work (because of this problem). I've seen some example projects where they do use types, how can it that they can use it? – Marvin Mar 03 '22 at 09:53
  • Thinking about it some more, it would fix the problem, since you hide a package with a module. – Karl Knechtel Mar 05 '22 at 23:28