Package configuration

As you develop more sophisticated modules and packages, you will often find that your code needs to be configured in some way before it can be used. For example, imagine that you're writing a package that uses a database. To do this, your package needs to know which database engine to use, the name of the database, and the username and password to use to access that database.

You could hardwire this information into your program's source code, but doing this is a very bad idea, for two reasons:

  • Different computers and different operating systems will use different database setups. Since the information used to access the database will vary from one computer to another, anyone wanting to use your package would have to edit the source code directly to enter the correct database details before the package can be run.
  • The username and password used to access a database is highly sensitive information. If you share your package with other people, or even just store a copy of your package's source code on a public repository such as GitHub, then other people can discover your database access credentials. This is a huge security risk.

These database access credentials are an example of package configuration—information that your package needs before it can run but which you don't want to build into your package's source code.

If you are building an application rather than a standalone module or package, your configuration task is much simpler. There are modules in the Python Standard Library that can help with configuration, for example, configparser, shlex, and json. Using these modules, you can store configuration settings in a file on disk, which the end user can edit. When your program starts, you load those settings into memory and access them as needed. Because the configuration settings are stored externally to your application, users won't have to edit your source code to configure the program, and you won't be exposing sensitive information if your source code is published or shared.

When writing modules and packages, however, the file-based approach to configuration is much less convenient. There's no obvious place to store a package's configuration file, and requiring configuration files at a particular location is going to make your module or package harder to reuse as part of a different program.

Instead, configuration for a module or package is usually done by supplying parameters to your module or package's initialization function. We saw an example of this in the previous chapter, where the quantities package required you to supply a locale value when initializing the package:

quantities.init("us")

This passes the job of configuration back to the surrounding application; the application can make use of a configuration file, or any other configuration scheme it likes, and it is the application that supplies the package's configuration settings when the package is initialized:

Package configuration

This makes things easier for the package developer as all the package needs to do is remember the settings it has been given.

While the quantities package only used a single configuration setting (the name of the locale), it is common for packages to use many settings. A very convenient way of supplying the configuration settings for a package is to use a Python dictionary. For example:

mypackage.init({'log_errors'  : True,
                'db_password' : "test123",
                ...})

Using a dictionary in this way makes it easy to support default values for your package's configuration settings. The following Python snippet shows how a package's init() function can accept configuration settings, supply default values, and store the settings in a global variable so that it can be accessed when needed:

def init(settings):
    global config

    config = {}
    config['log_errors']  = settings.get("log_errors",  False)
    config['db_password'] = settings.get("db_password", "")
    ...

Using dict.get() in this way, you retrieve the setting if one has been supplied, while providing a default value to use if the setting isn't specified. This is an ideal way of handling configuration within a Python module or package, making it simple for users of your module or package to configure it as required, while still leaving the details of how and where the configuration settings are stored up to the application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.200.71