How to read a config file using python - python

I have a config file abc.txt which looks somewhat like:
path1 = "D:\test1\first"
path2 = "D:\test2\second"
path3 = "D:\test2\third"
I want to read these paths from the abc.txt to use it in my program to avoid hard coding.

In order to use my example, your file "abc.txt" needs to look like this.
[your-config]
path1 = "D:\test1\first"
path2 = "D:\test2\second"
path3 = "D:\test2\third"
Then in your code you can use the config parser.
import ConfigParser
configParser = ConfigParser.RawConfigParser()
configFilePath = r'c:\abc.txt'
configParser.read(configFilePath)
As human.js noted in his comment, in Python 3, ConfigParser has been renamed configparser. See Python 3 ImportError: No module named 'ConfigParser' for more details.

You need a section in your file:
[My Section]
path1 = D:\test1\first
path2 = D:\test2\second
path3 = D:\test2\third
Then, read the properties:
import ConfigParser
config = ConfigParser.ConfigParser()
config.readfp(open(r'abc.txt'))
path1 = config.get('My Section', 'path1')
path2 = config.get('My Section', 'path2')
path3 = config.get('My Section', 'path3')

If you need to read all values from a section in properties file in a simple manner:
Your config.cfg file layout :
[SECTION_NAME]
key1 = value1
key2 = value2
You code:
import configparser
config = configparser.RawConfigParser()
config.read('path_to_config.cfg file')
details_dict = dict(config.items('SECTION_NAME'))
This will give you a dictionary where keys are same as in config file and their corresponding values.
details_dict is :
{'key1':'value1', 'key2':'value2'}
Now to get key1's value :
details_dict['key1']
Putting it all in a method which reads sections from config file only once(the first time the method is called during a program run).
def get_config_dict():
if not hasattr(get_config_dict, 'config_dict'):
get_config_dict.config_dict = dict(config.items('SECTION_NAME'))
return get_config_dict.config_dict
Now call the above function and get the required key's value :
config_details = get_config_dict()
key_1_value = config_details['key1']
Generic Multi Section approach:
[SECTION_NAME_1]
key1 = value1
key2 = value2
[SECTION_NAME_2]
key1 = value1
key2 = value2
Extending the approach mentioned above, reading section by section automatically and then accessing by section name followed by key name.
def get_config_section():
if not hasattr(get_config_section, 'section_dict'):
get_config_section.section_dict = collections.defaultdict()
for section in config.sections():
get_config_section.section_dict[section] = dict(config.items(section))
return get_config_section.section_dict
To access:
config_dict = get_config_section()
port = config_dict['DB']['port']
(here 'DB' is a section name in config file
and 'port' is a key under section 'DB'.)

A convenient solution in your case would be to include the configs in a yaml file named
**your_config_name.yml** which would look like this:
path1: "D:\test1\first"
path2: "D:\test2\second"
path3: "D:\test2\third"
In your python code you can then load the config params into a dictionary by doing this:
import yaml
with open('your_config_name.yml') as stream:
config = yaml.safe_load(stream)
You then access e.g. path1 like this from your dictionary config:
config['path1']
To import yaml you first have to install the package as such: pip install pyyaml into your chosen virtual environment.

This looks like valid Python code, so if the file is on your project's classpath (and not in some other directory or in arbitrary places) one way would be just to rename the file to "abc.py" and import it as a module, using import abc. You can even update the values using the reload function later. Then access the values as abc.path1 etc.
Of course, this can be dangerous in case the file contains other code that will be executed. I would not use it in any real, professional project, but for a small script or in interactive mode this seems to be the simplest solution.
Just put the abc.py into the same directory as your script, or the directory where you open the interactive shell, and do import abc or from abc import *.

Since your config file is a normal text file, just read it using the open function:
file = open("abc.txt", 'r')
content = file.read()
paths = content.split("\n") #split it into lines
for path in paths:
print path.split(" = ")[1]
This will print your paths. You can also store them using dictionaries or lists.
path_list = []
path_dict = {}
for path in paths:
p = path.split(" = ")
path_list.append(p)[1]
path_dict[p[0]] = p[1]
More on reading/writing file here.
Hope this helps!

For Pyhon 3.X:
Notice the lowercase import configparser makes a big difference.
Step 1:
Create a file called "config.txt" and paste the below two lines:
[global]
mykey = prod/v1/install/
Step 2:
Go to the same directory and create a testit.py and paste the code below into a file and run it. (FYI: you can put the config file anywhere you like you, you just have to change the read path)
#!/usr/bin/env python
import configparser
config = configparser.ConfigParser()
config.read(r'config.txt')
print(config.get('global', 'mykey') )

Related

List of windows path in configparse file in python

I am writting a script to backup a list of paths, inspired by https://github.com/Johanndutoit/Zip-to-FTP-Backup/blob/master/backup_to_ftp.py
So I have an ini file
[folders]
/home/david/docs
/home/david/images
/home/david/videos
[ftp]
username=etc
password=pwd
The code to read it is:
config = configparser.ConfigParser(allow_no_value=True)
config.optionxform = lambda option: option # preserve case for letters
config.read('backupcfg.ini')
filelistings = [] # All Files that will be added to the Archive
# Add Files From Locations
for folder in config.options("folders"):
filelistings.append(str(folder.strip("'")))
The problem is I can't find a way to read it as raw when I'm running it on windows, with folders like
[folders]
Z:\Desktop\winpython
I can't scape the backslash. I've ended up including it as:
filelistings = [r'Z:\docs\winpython', r'Z:\images\family']
Is there any way to write the paths in the ini? Can't find a way to read config.options("folders") to return raw.
Thank you for your help!
I have tried to add the path straight to the tar:
config = configparser.ConfigParser(allow_no_value=True)
config.optionxform = lambda option: option # preserve case for letters
config.read('backupcfg.ini')
now = datetime.datetime.now()
zipname = 'backup.' + now.strftime("%Y.%m.%d") + '.tgz'
with tarfile.open(zipname, "w:gz") as tar:
for name in config.options("folders"):
print ("Adding "+name)
tar.add(str(name))
Which reports can't find filename: 'Z'
Is there any way to access that information as it is, with ?
I got the idea for this answer from this answer. The problem isn't with the slashes. It's with the colon (:). By default, Configparser uses = and : as delimiters. But you can specify other delimiters to use instead.
backupcfg.ini
[folders]
/home/david/docs
Z:\Desktop\winpython
python code
import configparser
config = configparser.ConfigParser(allow_no_value=True, delimiters=(','))
config.optionxform = lambda option: option # preserve case for letters
config.read('backupcfg.ini')
for folder in config.options("folders"):
print(folder)
output:
/home/david/docs
Z:\Desktop\winpython

pathlib absolute path misbehaving with config parser

I have a following python3 script, that uses the config function to load data from a txt file that sits in the same directory where the script is located.
I've implemented the configparser module to extract the data, and pathlib module to set the absolute path to that file
from pathlib import Path
try:
import ConfigParser as configparser
except:
import configparser
def config():
parser = configparser.ConfigParser()
config_file = Path('config.txt').resolve()
parser.read(config_file)
return parser
then i pass it as an argument to the next method, which then gets the needed variables from the
config file:
def search_for_country(config):
country_name = config.get("var", "country_name")
the config.txt file is structured like this:
[var]
country_name = Brazil
The problem is: everything works fine if I run the script via Terminal from the same directory, but eventually it is intended to be run as a cron job, and if i try to execute it from one directory above, it returns the following error:
File "test/script.py", line 28, in search_for_country
country_name = config.get("var", "country_name")
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/configparser.py", line 781, in get
d = self._unify_values(section, vars)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/configparser.py", line 1149, in _unify_values
raise NoSectionError(section) from None
configparser.NoSectionError: No section: 'var'
Which seems to be telling that it cannot find the txt file.
So far I've tried out different options, for example using parser.read_file() instead of parser.read(), also tried this: https://stackoverflow.com/a/35017127/13363008
But none seem to be working. Maybe anyone could think of a cause to this problem?
so for Your problem :
import pathlib
path_own_dir = pathlib.Path(__file__).parent.resolve()
path_conf_file = path_own_dir / 'config.txt'
assert path_conf_file.is_file()
but why to store such config as text in the first place ?
"config is code" - so why limit Yourself with text config files ?
my usual way is :
# conf.py
class Conf(object):
def __init__(self):
country_name: str = 'Brazil'
conf=Conf()
# main.py
from .conf import conf
print(conf.county_name)
# override settings in the object
conf.county_name = 'Argentina'
print(conf.county_name)
it has so many advantages like having the correct data type,
having the IDE hints, avoiding the parsers, dynamically change settings, etc ...

Is there a way to remove part of a file name (path) in python?

I have around 50 files that have their name and then the date they were created at 3 times. How can I remove that part from the file name in python (You can show an example with other data it doesn't really matter)
I tried something like that:
file = 'directory/imagehellohellohello.png'
keyword = 'hello'
if (file.count(keyword) >= 3):
//functionality (here I want to remove the hello's from the file path)
This can be done quite simply using pathlib:
from pathlib import Path
path = Path("directory/imagehellohellohello.png")
target = path.with_name(path.name.replace("hello", ''))
path.rename(target)
And this indeed renames the file to "directory/image.png".
From Python version 3.8 the rename method also returns the new files' path as a Path object. (So it is possible to do:
target = path.rename(path.with_name(path.name.replace("hello", '')))
Methods/attributes used: Path.rename, Path.with_name, Path.name, str.replace
file = 'directory/imagehellohellohello.png'
keyword = 'hello'
if keyword*3 in file:
newname = file.replace(keyword*3, '')
os.rename(file, newname)

Is it possible to dump the yaml file in another directory on same system?

Here is my directory on raspberry pi:
Home
|__pi
|__test1
|__test2
|__ abc.py
I am running a python code (abc.py) that edit and then dump a YAML file. But the file is saved in the same directory (i.e in test2). Is it possible to dump the YAML file in another directory (i.e in test1)?
If yes, then please let me know the code.
Here is my python code:
import sys
from ruamel.yaml import YAML
inp = """\
# example
name:
# details
family: Smith # very common
given: Alice # one of the siblings
"""
yaml = YAML()
code = yaml.load(inp)
code['name']['given'] = 'Bob'
yaml.dump(code, sys.stdout)
The second parameter to the .dump() method can be a stream like sys.stdout or a stream that is an opened file:
with open('../code1/output.yaml', 'w') as fp:
yaml.dump(code, fp)
As you are on Python3, you also have pathlib as part of the standard library and you can pass a pathlib.Path as second parameter to .dump():
from pathlib import Path
output = Path('../code1/output.yaml')
yaml.dump(code, output)
The Path will be properly opened for writing and closed.
(You can also load from a Path by doing, yaml.load(Path('some/path/to/a/file')))

Python ConfigParser cannot search .ini file correctly (Ubuntu 14, Python 3.4)

Problem:
The code compiles fine but when ever i call the read_db_config function i get "Exception: mysql not found in the mysql_config.ini file"
The file is in the same directory but the main script runs two directories up using
import sys
from Config.MySQL.python_mysql_dbconfig import read_db_config
I am new to python and have searched everywhere but i cannot seem to pinpoint my issue
Code:
from ConfigParser import ConfigParser
def read_db_config(filename='mysql_config.ini', section='mysql'):
# create parser and read ini configuration file
parser = ConfigParser()
parser.read(filename)
# get section, default to mysql
db = {}
if parser.has_section(section):
items = parser.items(section)
for item in items:
db[item[0]] = item[1]
else:
raise Exception('{0} not found in the {1} file'.format(section, filename))
return db
mysql_config.ini:
[mysql]
database = testdba
user = root
password = test
unix_socket = /opt/lampp/var/mysql/mysql.sock
if you use relative paths for file or directory names python will look for them (or create them) in your current working directory (the $PWD variable in bash).
if you want to have them relative to the current python file, you can use (python 3.4)
from pathlib import Path
HERE = Path(__file__).parent.resolve()
CONFIG_PATH = HERE / '../etc/mysql_config.ini'
or (python 2.7)
import os.path
HERE = os.path.abspath(os.path.dirname(__file__))
CONFIG_PATH = os.path.join(HERE, '../etc/mysql_config.ini')
if your mysql_config.ini file lives in the etc directory below your python script.
you could of course always use absolute paths (starting with a /; i.e. /home/someuser/mysql_config.ini).
I ran it again but with the modification of adding
parser = configparser.ConfigParser()
parser['mysql'] = {'database': 'testdba',
'user' : 'root',
'password' : 'test',
'unix_socket' : '/opt/lampp/var/mysql/mysql.sock'}
with open('mysql_config.ini', 'w') as configfile:
parser.write(configfile
and I found that this created the file "mysql_config.ini" not in the directory where the python "read_db_config" was stored but the parent directory of main python module which calls this module. I searched it up a bit and figured out a perment solution the lets me keep the "mysql_config.ini" where I wish.
import configparser
def read_db_config(dirname = '/opt/Python_MySQL_Email_Receipt_Client/Config/MySQL/', filename='mysql_config.ini', section='mysql'):
# create parser and read ini configuration file
parser = configparser.ConfigParser()
parser.read(dirname + filename)
# get section, default to mysql
db = {}
if parser.has_section(section):
items = parser.items(section)
for item in items:
db[item[0]] = item[1]
else:
raise Exception('{0} not found in the {1} file'.format(section, filename))
return db

Categories

Resources