One config file for the whole python application
I am a bit new to Python (but not at all for programming already fluent in Perl, PHP and Ruby). I faced a significant difference between all my previous languages ββand Python: basically, I can easily read data from another file into the whole project. there are two main examples of this that I would like to solve:
1) I would like to have a settings / config file (in YAML) that is read and parsed in the config.py file. Then I want the resulting dict () to be available to all my other files in the project. I figured out how to do it using from lib.project.config import cfg
, but that means that for every page that imports the configurations, the system has to REparse yaml. It just seems silly to me. Is there no way for this file to be processed only once and then the results are available to any other file in my project?
2) I would like to import a database.py file which then looks at my configs to see if we need to import the sqlite3, mysql or postgresql version of the database class. Again, I can handle this by putting logic directly on each page for which I need a database class. But I don't like to embed code like
if cfg.get('db_type') == 'sqlite':
from lib.project.databases.sqlite3 import database
elif cfg.get('db_type') == 'mysql':
from lib.project.databases.mysql import database
at the top of each file that needs a database class. I would just add:
import lib.project.database
Any help would be much appreciated. I did a lot of googling and searching and didn't find any answers. Hopefuly one of you wiz out there can help.
Thank.
UPDATE: The reason I do it like this (for # 2) is because I am also trying to get other classes to inherit from the database class. So lib / project / databases / sqlite.py is the definition of the database class. And this is also lib / project / databases / mysql.py. The idea is that after the import is complete, I can import classes like the user class and define it like this:
class user(database):
...
And thus inherits all the structure and methods of the database class. Your suggestions to just create an instance based on sqlite / mysql logic / solution and then pass that where it should be is a good solution for that. But I need a little more ... Ideas?
source to share
1) you're all set - the file will only be read once.
2) Agreed that you don't want to copy any sticky code like this: if you want to use 1 instance of the database in your entire project, you would do something like:
import lib.project db = lib.project.database
where db
is just a local variable used to access the already created database. You have to create your database as database
(allowing as you did with code to if/elif
use sqlite3 or mysql) in lib/project/databases.py
and then in your lib/project/__init__.py
file you do from .databases import database
.
if you want to use multiple databases (of the same sqlite3 / mysql type) throughout your project, you have to decide which constructor is database
bound to (or inherited) in databases.py
:
from lib.project.Config import config
if config.db_type == 'sqlite' :
import lib.project.databases.Sqlite as Db
elif config.db_type == 'mysql':
import lib.project.databases.Mysql as Db
class Database(Db):
'''docs'''
source to share
Thank you for helping me understand Python and how to get what I'm looking for.
Here's what I did:
1) Config file issue: This seems to have been mostly addressed to begin with. I confirmed that everyone says that you can "import" the file as many times as you want, but it only gets processed / processed / compiled once. As for making it available to whatever file it needs: Configuration class:
import os
import yaml
class Config:
def __init__(self):
self.path = os.getcwd()
stream = open(self.path+"/conf/config.yaml", 'r')
data = yaml.load(stream)
config_keys = data.keys()
for k in config_keys:
setattr(self, k, data.get(k))
if (os.path.isfile(self.path+"/conf/config-override.yaml") ):
stream = open(self.path+"/conf/config-override.yaml", 'r')
data = yaml.load(stream)
config_keys = data.keys()
for k in config_keys:
setattr(self, k, data.get(k))
config = Config()
And then any file that wants to use it:
from lib.project.Config import config
This still works.
2) Dynamic database type for the database class: I only changed my general design a little to make the database class (mostly empty) inherit from either Sqlite classes or Mysql (as custom assemblies that are wrappers for existing Sqlite classes and mysql connectors). This way, there is always a reliable database class to inherit from, I only load the files I need and it is all determined by my config file. Example: Database class:
from lib.project.Config import config
if config.db_type == 'sqlite' :
from lib.project.databases.Sqlite import Sqlite
elif config.db_type == 'mysql':
from lib.project.databases.Mysql import Mysql
class Database(Sqlite if config.db_type == 'sqlite' else Mysql):
''' documentation '''
I would still love to hear people's feedback on this code / method. As I said, I am still new to Python and may still be missing something.
Thanks again everyone.
source to share