0

My ipmi_server.py file is bellow:

#!/usr/bin/python3
#-*- coding:utf-8 -*-
# Author: dele


import socket
from .ipmi_util import ipmi_handler

from .allowed_ip import allowed_ip_list   

HOST = '4.24.124.29'
PORT = 65432



with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    while True:
        conn, addr = s.accept()
        with conn:
            print('Connected by', addr)

            if addr and addr[0] not in allowed_ip_list:
                conn.sendall('invalid ip')

            else:

                while True:
                    data = conn.recv(1024)
                    if not data:
                        break

when I run the ipmi_server.py file, there get bellow error:

dele-MBP:ipmi_management ldl$ python3 ipmi_server.py 
Traceback (most recent call last):
  File "ipmi_server.py", line 7, in <module>
    from .ipmi_util import ipmi_handler
SystemError: Parent module '' not loaded, cannot perform relative import

the directory tree is bellow:


I have checked the post, but did not found the solution.

--

EDIT-01

I tried the

from ipmi_management.ipmi_util import ipmi_handler

but get bellow error:

dele-MBP:ipmi_management ldl$ python3 ipmi_server.py 
Traceback (most recent call last):
  File "ipmi_server.py", line 7, in <module>
    from ipmi_management.ipmi_util import ipmi_handler
ImportError: No module named 'ipmi_management'
user7693832
  • 6,119
  • 19
  • 63
  • 114
  • 1
    Possible duplicate of [How to fix "Attempted relative import in non-package" even with \_\_init\_\_.py](https://stackoverflow.com/questions/11536764/how-to-fix-attempted-relative-import-in-non-package-even-with-init-py) – ch0wner Apr 23 '19 at 11:00
  • One possible and simple way to think about this is realizing that if this is a package to be used as such, the execution entry point should not rest inside it. If you import `ipmi_management` package from a top-level client script, the inner relative imports shoulld work fine. – progmatico Apr 23 '19 at 11:12

1 Answers1

2

You cannot use relative imports if you run the ipmi_server directly.

The reason for this is that the relative imports are used relatively to the __name__ of the current file.

Referring to the official python docs

A module’s __name__ is set equal to __main__ when read from standard input, a script, or from an interactive prompt.

You were running the module as a script thus relative imports will not work.

You can run this as a package from the root folder of your project (notice this is executed as a package, thus I've omitted the .py extension)

python -m ipmi_management.ipmi_server

Or alternatively replace the relative imports by absolute imports as documented here:

from ipmi_management.ipmi_util import ipmi_handler

Edit -01


Well as explained well in this answer this would work only if you would import the script interactively.

When executing the script from commandline the sys.path[0] will be equal to the path of the directory that contains the module that you are executing. Even running the module from the project root likewise: python ipmi_management/ipmi_server.py will make no difference.

For example if your module was located at:

/home/user/projects/qiyun_ipmi_management/ipmi_management/ipmi_server.py', sys.path[0] would be equal to/home/user/projects/qiyun_ipmi_management/ipmi_management/'

The way python imports work, as documented here, the interpreter will simply have no clue where to find the ipmi_management package.

While the first option I suggested still holds, running a module from within a package is not recommended, you should adapt your project to allow for the ipmi_management to be used as package:

Change the ipmi_server.py code as the following:

def run_server():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        while True:
            conn, addr = s.accept()
            with conn:
                print('Connected by', addr)

                if addr and addr[0] not in allowed_ip_list:
                    conn.sendall('invalid ip')

                else:

                    while True:
                        data = conn.recv(1024)
                        if not data:
                            break

add a __main__.py module to your ipmi_management package which then makes use of the ipmi_server.py code like so:

from ipmi_management.ipmi_server import run_server

def main():
    run_server()

if __name__ == '__main__':
    main()

And by running python -m ipmi_management from the project root will result in the ipmi_server.py being called and the server being run.

Note that I still used absolute imports as they are recommended by PEP-8

Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on sys.path):

If you really wish to run the ipmi_server.py module directly, you could use insert the parent directory of that module to sys.path but this is considered unpythonic and generally a bad habit as it makes the python importing system even more obscure.

ch0wner
  • 349
  • 1
  • 10