Use python as the configuration file

Source: Internet
Author: User
There is no doubt that you need a configuration file. It is said that the configuration file can make your system customizable.
There are three major trends in customizing the system, which determine the format of the three configuration files:

1. graphical interface configuration tool.

Since the popularity of computers and Windows, our users are no longer hackers,
Maybe your user will never open your configuration file. You need to give him a graphical tool and change his diapers.

When humans never read the configuration file, the more concise way to make the system is to use
Generally, this is a binary file.
Pickle is a typical option in Python.

After a few decades, some people began to think that using the format that both machines and people can understand (or cannot understand) is a good idea, so that XML is available.
Here, I just want to tell you:

XML is really a good thing, but in most cases you don't really need it.

In Zope/plone, configurations are stored in the zodb database on a large scale.

In this way, the first configuration file type is generated, which is unreadable by humans.

2. configuration files in common format, including the famous httpd. conf and ini.

Basically, INI is weak, and the INI support library does not provide functions such as value verification or even setting the default value of variables,
Therefore, unless the project is very small, you should not use the INI format.

The INI format is not used at any time, which helps you develop good habits.

The configuration file of httpd. conf like is the peak of the configuration file format.
In python, zconfig (located in zope2/zope3) provides support for this format.

Here is an introduction:
Http://eishn.blog.163.com/blog/static/65231820069310828642/

It is just an introduction. You need to read the documentation, source code, or examples to fully understand how zconfig works.
Although it is not easy, understanding zconfig will help you quickly master the design philosophy of the configuration file.

Conventional configuration file design and parsing are too complex, so you can only understand.

3. Use python as the configuration file.

Why not? Currently, many C Programs are using python as the configuration file,
The Lighttpd configuration file is no longer the same.

Here is an example:

# Demo_conf.py
# Configuration file
Host = '2017. 0.0.1'
Port = 8080

# Demo. py
Import demo_conf
Print demo_conf.host, demo_conf.port

The Python script is used as the configuration file, which is simple in program implementation without format conversion and has powerful functions.
This scheme has begun to declare war on the traditional configuration file format.

Finally, I modified the original plan to introduce zconfig. Today I will introduce this scheme again.


Next, let's design our own configuration file format.

To figure out how to design a configuration file, we need to first figure out which data types in the system need to be configured,
And find out to what extent they can be configured.

Based on experience, three types of data can be customized in a system:

1. "static" data is defined by # define in the C language.
Such data is dynamic only during the development period. Once the system completes development, such data is static.
This type of data has the lowest change frequency.

Python programmers usually write the variable name up and put it in "config. py,
Import and use through import config.

2. "default" configuration, which is the biggest source of chaos in the project configuration.
The default configuration is the data that users can modify in the configuration file. They are not mandatory and have default values.

You will soon find that many "default" configurations will never be modified by users,
In this case, these default configurations are actually the "static" data mentioned above and should be written into "config. py ".
Others are common configurations with default values. The data should be written to the "etc" configuration file.

Obviously, a variable cannot exist in both config. py and etc configuration files.
The problem is that it is difficult and uncertain to determine whether a variable belongs to "static" data or "default" configuration.
This eventually led to the changing definition of your configuration file, and your project was in a storm.

3. configuration items should be placed in the configuration file without any doubt. After the system is put into use, this is the data type with the highest change frequency.

Another major challenge in the configuration file is variable type verification.
Variable type verification is annoying because you need to determine whether a configuration variable exists, whether the type matches, or whether it is out of bounds at the same time,
And whether to give the default value. The worst thing is that you still need to answer one question:

Whether the default value needs to be written in the configuration file.

To solve all these problems, schema was invented.
Unlike traditional configuration files, using python as a configuration file makes schema compilation quite flexible.
In addition, the schema helps you make the configuration file in the python format more readable.
The following shows how to write a schema when python is used as the configuration file format.

#/Path/to/etc/demo_conf.py
# Configuration file

Import Schema

Server (
Host = '2017. 0.0.1 ',
Port = 8080
)

#-EOF-



#/Path/to/etc/Schema. py
#

Config = {}

Def server (** ARGs ):
Config ['host'] = args. Get ('host', '0. 0.0.0 ') # default value available

Try:
Config ['Port'] = int (ARGs. Get ('Port', 8080) # With verification
Failed t valueerror:
Raise valueerror, 'you must be an integer'

#-EOF-



#/Path/to/bin/demo. py
#

Import sys
SYS. Path. append (R'/path/to/etc ')

Import schema, demo_conf
Print schema. config ['host'], schema. config ['Port']

#-EOF-

Now, we need to make demo_conf.py more like a configuration file,
Because "Import schema" is not something in a configuration file, we need to make "server" A preimported variable.
Finally, we need to change demo_conf.py to demo. conf.

In this way, we will be able to access custom import technology again after pyqt4 is a breeze.
This time we will use a similar technique, which is also an import hook. The difference is that this time we will not hook the hook to the python interpreter.


######################################## ##########################-Bof-
# Pyetc. py

# Python-format configuration file support library
#
Import sys, OS. Path

Module = type (sys) # Replay
Modules = {}# cache the imported etc (configuration) Module


# Import any file conforming to the python syntax
# Usage:
# Module = pyetc. Load (the complete file path contains the extension, preload variables, and custom return module types)
#
Def load (fullpath, ENV ={}, module = module ):
Try:
Code = open (fullpath). Read ()
Handle t ioerror:
Raise importerror, 'no module named % s' % fullpath

Filename = OS. Path. basename (fullpath)

Try:
Return modules [filename]
Failed t keyerror:
Pass

M = module (filename)
M. _ module_class _ = Module
M. _ file _ = fullpath

M. _ dict _. Update (ENV)

Exec compile (Code, filename, 'exec ') in M. _ dict __
Modules [filename] = m

Return m

# Remove imported modules
# Usage:
# Module = unload (module)
#
Def unload (m ):
Filename = OS. Path. basename (M. _ file __)
Del modules [filename]

Return none

# Re-import module
# Usage:
# Module = pyetc. Reload (module)
#
Def reload (m ):
Fullpath = M. _ file __

Try:
Code = open (fullpath). Read ()
Handle t ioerror:
Raise importerror, 'no module named % s' % fullpath

ENV = M. _ dict __
Module_class = M. _ module_class __

Filename = OS. Path. basename (fullpath)
M = module_class (filename)

M. _ file _ = fullpath
M. _ dict _. Update (ENV)
M. _ module_class _ = module_class

Exec compile (Code, filename, 'exec ') in M. _ dict __
Modules [filename] = m

Return m

######################################## ##########################-EOF-


Next let's try it.

#/Path/to/etc/demo. conf
# Configuration file

Host = '2017. 0.0.1'
Port = 8080

#-EOF-



# Demo. py
Import pyetc
Conf = pyetc. Load (R'/path/to/etc/demo. conf ')

Print Conf. Host, Conf. Port
#-EOF-


Finally, a complete example is provided:

#/Path/to/etc/demo. conf
# Server options
#

Server (
Port = 8080 # Listen to port 8080
)


# Process controller options
#

Daemon (
# Use SOCKET to publish a process Controller
# Address = ('0. 0.0.0 ', 10080 ),

# Use the File publishing process Controller
Address = VAR ('demo. PID '),

# Server process
Program = Bin ('server. py '),

# Debugging Switch
Verbose = true
)

#-EOF-




#/Path/to/bin/Schema. py
# Path tool
Import sys, OS. Path
Demo_home = R'/path/to/demo'

ETC = Lambda filename: OS. Path. Join (demo_home, 'etc ', filename)
Var = Lambda filename: OS. Path. Join (demo_home, 'var', filename)
Bin = Lambda filename: OS. Path. Join (demo_home, 'bin', filename)

#
Class config (dict ):
# You can access the dictionary key like an attribute.
# Dict. Key is equivalent to dict [Key]

Def _ getattr _ (self, name ):
Return self [name]

# Default Configuration
Config = config ({
'Server': config ({
'Port': 8080 # The server uses port 8080.

}),

'Daemon': config ({
'Address': VAR ('daemon. Pi'), # PID File
'Signature': Bin ('server. py'), # server program
'Verbo': True

})
})

# Configuration interface (without verification)
Def server (** ARGs ):
Config ['server']. Update (ARGs)

Def daemon (** ARGs ):
Config ['daemon']. Update (ARGs)

# VARIABLES visible in the configuration file "demo. conf"
ENV = {'server': Server, 'daemon': daemon,
'Etc ': etc, 'var': var, 'bin': Bin}

#-EOF-




#/Path/to/bin/demo. py
# Start a daemon manager,
# Note: The daemon. py here is a hypothetical library, so ignore it.

Import pyetc
From daemon import daemon

Def start ():
# Reading configuration files
# Demo. conf
Pyetc. Load (schema. etc ('demo. conf'), ENV = schema. env)
Conf = schema. config. Daemon

# Create a daemon object
Daemon = daemon (
Address = Conf. Address, # process controller address/PID File Location
Program = Conf. Program, # background process program location
Verbose = Conf. verbose # debugging
)

Print 'process manager started'

Daemon ()

If _ name _ = '_ main __':
Start ()

#-EOF-
from: http://eishn.blog.163.com/blog/static/6523182007236721876/
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.