Florent
Florent

Reputation: 1928

How to import a Python module with relative path to a file from another directory?

I have a Python project with subdirectories and I'm unable to import a module located in the root directory, here logger.py, from another module in a subdirectory, here composite.py.

The problem is that logger.py point to a log file in the log directory with a relative path name to it, so composite.py can't find this file from it's sub directory.

How can I import module logger from composite.py and from another module in the root directory, like module.py ?

├── data/
    module.py
    logger.py
    ├── composite/
    │   ├── composite.py
    ├── log/
    │   ├── info.log

This work :

data/logger.py:

h_info =      RotatingFileHandler('log/info.log', [...])

data/module.py:

import logger

This doesn't work:

data/composite/composite.py:

from data import logger

FileNotFoundError: [Errno 2] No such file or directory: '/home/abc/project/python/xyz/data/composite/log/info.log'

Upvotes: 0

Views: 267

Answers (1)

Jean-François Fabre
Jean-François Fabre

Reputation: 140168

It doesn't work because your code is relying on the current directory to open the log file.

Since you know the relative path to your log file from the file you're opening the log, you can use os.path.dirname(__file__) to locate the current directory module then join the rest:

in logger.py, os.path.dirname(__file__) is '/home/abc/project/python/xyz/data'. Just add the log folder part.

h_info = RotatingFileHandler(os.path.join(os.path.dirname(__file__),'log/info.log'), [...])

or in a more portable way:

h_info = RotatingFileHandler(os.path.join(os.path.dirname(__file__),"log","info.log"), [...])

NEVER reference resource/external files with a relative path. Always use either absolute path from a config file or use this technique to be sure of the starting directory. Never use os.chdir either to do this.

Similar issue: Weird python file path behavior path-behavior

Interesting related read: os.getcwd() vs os.path.abspath(os.path.dirname(__file__))

Upvotes: 3

Related Questions