Необходимо было создать скрипт для редактирования файлов настроек приложения, что бы не изменять его вручную.
В скрипте используется модуль ConfigParser
(ссылки в конце поста).
Можно вызывать либо с передачей опций (модуль argparce
), либо — без опций.
В случае вызова с опциями — можно указать какой файл редактировать, иначе — будет использован файл по умолчанию (default=CONF_DIR + '/external.properties'
в parser.add_argument
).
Пример файла конфигурации:
[Connection settings] jdbc.main.url = jdbc:oracle:thin:@host1 jdbc.main.username = USER jdbc.main.password = pass [Mail settings] mail.smtp.host=127.0.0.1 mail.smtp.port=25 mail.smtp.on=false mail.cronExpression=0 0/2 * ? * MON-SUN [Import cron expressions] gateKeeper.cronExpression=0 0 5 ? * MON-SUN cleanup.compress.cronExpression=0 0 12 ? * SUN send.mails.to.group.cronExpression = 0 0 12 ? * MON-SUN exc_tckt_d.cronExpression=0 30 22 ? * MON-FRI [Gate keeper settings] gk.homedir=gate_keeper_report sftp.useLocalFileIfAvailable=true sftp.downloadBaseDir=~/download sftp.maxRetryLimit=3 [TCP Report Extract Properties] usePrecalculatedAggregation=true [Other settings] bean.datasource.query_log_wrapper=mainDataSourceWrapper log.client.exception = false time.to.keep.domain=7*12 time.to.keep.uncompress=1 dao.batch.size.max=30
И сам скрипт:
#!/usr/bin/env python import os import sys import re import logging import time import ConfigParser import argparse ENV = os.environ['ENV'] CONF_DIR = os.path.join(os.environ['HOME'], 'secure') LOG = os.path.join(os.environ['HOME'], 'logs/settings.log') logging.basicConfig(format = '%(filename)s[LINE:%(lineno)d] - %(levelname)-3s [%(asctime)s] %(message)s ', filename=LOG, level=logging.DEBUG) parser = argparse.ArgumentParser() parser.add_argument('-f', '--file', default=CONF_DIR + '/external.properties', help='File to edit, default $HOME/secure/external.properties') parser.add_argument('-s', '--section', help='Block name to edit option in') parser.add_argument('-o', '--option', help='Option name to edit option in') parser.add_argument('-v', '--value', help='New value, to set in option from --option') RES = parser.parse_args() print("nWorking on %s and using configuration directory %s.n" % (ENV,CONF_DIR)) logging.info('Setting edit started at %s' % (time.ctime())) def answer(prompt, choice='Yes or no, please!'): '''Used for user communication, to confirm selected item. Return True if 'y' and False if 'n' entered.''' while True: result = raw_input(prompt) if result in ('y', 'Y', 'yes', 'Yes'): return True elif result in ('n', 'N', 'no', 'No'): return False else: print(choice) def select_conf(path): '''Used to select configuration file from directory in CONF_DIR variable. Return filename without full path.''' while True: list = [] for file in os.listdir(path): list.append(file) print('%s %s' % ((list.index(file)), file)) try: res_file = int(raw_input('nPlease, select file to edit: ')) print('You selected: %s' % list[res_file]) except ValueError as e: print('Please, enter correct value: %sn' % e) sys.exit(2) if answer('Is it OK? [y/n] '): logging.info('Selected %s file to work with.' % list[res_file]) return(list[res_file]) break def select_section(configfile): '''Use ConfigParser module to select sections, declared in [] blocks in file. File takes from select_conf() function.''' Config = ConfigParser.ConfigParser() file = os.path.join(CONF_DIR, configfile) list = [] try: Config.read(file) except ConfigParser.MissingSectionHeaderError as e: print(e) sys.exit(5) print('n') while True: for section in Config.sections(): list.append(section) print('%s %s' % ((list.index(section)), section)) try: res_section = int(raw_input('nPlease, select section to edit: ')) print('You selected: %s' % list[res_section]) except ValueError as e: print('Please, enter correct value: %sn' % e) sys.exit(3) if answer('Is it OK? [y/n] '): logging.info('Selected %s section to work with.' % list[res_section]) return(list[res_section], file) break def write_changes(file, section, option, value): file = os.path.join(CONF_DIR, file) print('Editing file: %s. Will set section: %s, option: %s, value: %s.n' % (file, section, option, value)) Config = ConfigParser.ConfigParser() Config.read(file) Config.set(section, option, value) with open(file, 'r+') as c_file: Config.write(c_file) print('New value assigned successfully.') logging.info('New value assigned successfully. Finished at %s' % (time.ctime())) def edit_option(*args): '''If script called without arguments: Use $section variable from select_section() function, to set section, to select options from, and $file variable from select_section() function, to set file, to be edited. First loop - to set new variable $res_option, where option to be edited saves; second loop - to set new varaible $new_value, to be saved in $section in $file. next. in second loop, with ConfigParcer - writing new $new_value in $file. If called with arguments: will set RES.file, RES.section, RES.option and RES.value from parser.parse_args()''' Config = ConfigParser.ConfigParser() if len(sys.argv) <= 1: section, file = select_section(select_conf(CONF_DIR)) list = [] Config.read(file) print('n') while True: for option in Config.options(section): list.append(option) print('%s %s' % ((list.index(option)), option)) try: res_option = int(raw_input('nPlease, select option to edit: ')) print('You selected: %s' % list[res_option]) except ValueError as e: print('Please, enter correct value: %sn' % e) sys.exit(4) if answer('Is it OK? [y/n] '): logging.info('Selected %s option to work with.' % list[res_option]) break while True: print('nCurrent value of %s is %s.n' % (list[res_option], Config.get(section, list[res_option]))) logging.info('Current value of %s is %s.' % (list[res_option], Config.get(section, list[res_option]))) new_value = raw_input('Please, set new value for %s: ' % list[res_option]) print('Your new value for %s is %s.' % (list[res_option], new_value)) logging.info('Entered new value %s.' % new_value) if answer('Is it OK? [y/n] '): write_changes(file, section, list[res_option], new_value) break else: logging.info('Running optional edit. File: %s; section: %s, option: %s, new value: %s' % (RES.file, RES.section, RES.option, RES.value)) write_changes(RES.file, RES.section, RES.option, RES.value) if __name__ == "__main__": try: edit_option(RES.section) except KeyboardInterrupt: logging.info('Exited by KeyboardInterrupt at %s.' % (time.ctime())) print('n') sys.exit(0)
Его работа, при вызове без опций:
$ ./setting.py Working on DEV and using configuration directory /home/user/secure. 0 external.DEV.properties-NEW 1 external.properties_2014-11-29-12_44_bak 2 external.properties_2014-11-29-12_45_bak 3 external.properties-30_12_2014 4 test.property 5 external.properties 6 external.properties_encoding_bkp 7 secret.key Please, select file to edit: 4 You selected: test.property Is it OK? [y/n] y 0 Connection settings 1 Gate keeper settings 2 TCP Report Extract Properties 3 Mail settings 4 Import cron expressions 5 Other settings Please, select section to edit: 0 You selected: Connection settings Is it OK? [y/n] n 0 Connection settings 1 Gate keeper settings 2 TCP Report Extract Properties 3 Mail settings 4 Import cron expressions 5 Other settings Please, select section to edit: 0 You selected: Connection settings Is it OK? [y/n] y 0 jdbc.main.url 1 jdbc.main.password 2 jdbc.main.username Please, select option to edit: 0 You selected: jdbc.main.url Is it OK? [y/n] y Current value of jdbc.main.url is host2. Please, set new value for jdbc.main.url: host_new.com Your new value for jdbc.main.url is host_new.com. Is it OK? [y/n] y New value assigned successfully.
Лог:
setting.py[LINE:19] - INFO [2014-12-30 14:00:43,339] Setting edit started at Tue Dec 30 14:00:43 2014 setting.py[LINE:58] - INFO [2014-12-30 14:00:47,948] Selected test.property file to work with. setting.py[LINE:94] - INFO [2014-12-30 14:00:57,852] Selected Connection settings section to work with. setting.py[LINE:130] - INFO [2014-12-30 14:01:02,164] Selected jdbc.main.url option to work with. setting.py[LINE:136] - INFO [2014-12-30 14:01:02,164] Current value of jdbc.main.url is host2. setting.py[LINE:139] - INFO [2014-12-30 14:01:09,916] Entered new value host_new.com. setting.py[LINE:146] - INFO [2014-12-30 14:01:11,260] New value assigned successfully. Finished at Tue Dec 30 14:01:11 2014
Вызов с опциями, без указания файла, который редактировать:
$ ./setting.py -s "Connection settings" -o "jdbc.main.url" -v "besturlever.db.com" Working on DEV and using configuration directory /home/user/secure. Editing file: /home/user/secure/external.properties, section: Connection settings, option: jdbc.main.url, value: besturlever.db.com. New value assigned successfully.
И с указанием файла:
$ ./setting.py -f "test.property" -s "Connection settings" -o "jdbc.main.url" -v "besturlever.db.com" Working on DEV and using configuration directory /home/user/secure. Editing file: /home/user/secure/test.property. Will set section: Connection settings, option: jdbc.main.url, value: besturlever.db.com. New value assigned successfully.
Ссылки по модулю ConfigParser
http://www.pythonforbeginners.com