38

I have the following directory structure:

my_program/
       foo.py
       __init__.py # empty
       conf/
          config.cfg
          __init__.py 

In foo.py I have this:

import sys 
#sys.path.append('conf/')
import ConfigParser

config = ConfigParser.ConfigParser()
config.read( 'conf/config.cfg' )

In conf/__init__.py I have

__all__ = ["config.cfg"]

I get this error in foo.py that I can fix by giving the full path but not when I just put conf/config.cfg but I want the relative path to work:

ConfigParser.NoSectionError

which actually means that the file can't be loaded (so it can't read the section).

I've tried commenting/un-commenting sys.path.append('conf/') in foo.py but it doesn't do anything.

Any ideas?

vvvvv
  • 25,404
  • 19
  • 49
  • 81
ale
  • 11,636
  • 27
  • 92
  • 149

3 Answers3

61

Paths are relative to the current working directory, which is usually the directory from which you run your program (but the current directory can be changed by your program [or a module] and it is in general not the directory of your program file).

A solution consists in automatically calculating the path to your file, through the __file__ variable that the Python interpreter creates for you in foo.py:

import os
config.read(os.path.join(os.path.dirname(__file__), 'conf', 'config.cfg'))

Explanation: The __file__ variable of each program (module) contains its path (possibly relative to the current directory when it was loaded, I guess—I could not find anything conclusive in the Python documentation—, which happens for instance when foo.py is imported from its own directory).

This way, the import works correctly whatever the current working directory, and wherever you put your package.

PS: side note: __all__ = ["config.cfg"] is not what you want: it tells Python what symbols (variables, functions) to import when you do from conf import *. It should be deleted.

PPS: if the code changes the current working directory between the time the configuration-reading module is loaded and the time you read the configuration file, then you want to first store the absolute path of your configuration file (with os.path.abspath()) before changing the current directory, so that the configuration is found even after the current directory change.

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
  • 1
    Thank you. Same problem though I'm afraid: `import os` `import ConfigParser` `config = ConfigParser.ConfigParser()` `config.read( os.path.join( os.path.dirname( __file__ ), 'conf', 'config.cfg' ) )` raises the same error as before. I have removed the `__all__ = ["config.cfg"]` too – ale Dec 10 '12 at 12:24
  • If I print the path then it correctly says `./conf/config.cfg` which is strange! – ale Dec 10 '12 at 12:38
  • Can you try with the updated version of the answer? it uses an absolute path instead of a possibly relative one. – Eric O. Lebigot Dec 11 '12 at 02:11
  • 1
    Sorry, still doesn't work :). It now prints `/conf/config.cfg`. – ale Dec 11 '12 at 12:14
  • From what directory do you run your program and/or import my_program.foo? – Eric O. Lebigot Dec 11 '12 at 14:40
  • `foo.py` is a daemon. Inside `foo` is class (`Foo`) that is instantiated from within the same file (is this okay?). `Foo` is inherits from http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ hope that helps? Thank you very much. – ale Dec 11 '12 at 15:13
  • 1
    Then you have to handle the fact that the current working directory is changed during instantiation (there is a `os.chdir("/")`) in the class you link to. Adding details to your question seems important, at this point: when do you instantiate `Foo` (which changes the current working directory) compared to your configuration reading? etc. My current guess is that you should get the file path *before* instantiating `Foo` (you can store it in a variable and use it later, if need be). Does this work? – Eric O. Lebigot Dec 12 '12 at 04:11
  • _all_ = ["config.cfg"] in _init_.py is not required. Answer works pefectly fine. – Sufiyan Ansari Jun 26 '19 at 12:00
3

you can use os package in python for importing an absolute or relative path to the configuration file. Here is a working example with the relative path (we suppose that config.ini in the folder name configuration that is in the subdirectory of your python script folder):

import configparser
import os

path_current_directory = os.path.dirname(__file__)
path_config_file = os.path.join(path_current_directory, 'configuration', config.ini)
config = configparser.ConfigParser()
config.read(path_config_file)
Dr. Arslan
  • 1,254
  • 1
  • 16
  • 27
-6

Just load the path from a Variable and why so complex?

 from configparser import ConfigParser

 prsr=ConfigParser()
 configfile="D:\Dummy\DummySubDir\Dummy.ini"
 prsr.read(configfile)
 print(prsr.sections())
Shiva
  • 21
  • 1
  • 5