{"id":503,"date":"2018-01-01T08:00:40","date_gmt":"2018-01-01T08:00:40","guid":{"rendered":"http:\/\/buklijas.info\/blog\/?p=503"},"modified":"2017-12-31T11:23:45","modified_gmt":"2017-12-31T11:23:45","slug":"always-start-with-simple-solution","status":"publish","type":"post","link":"http:\/\/buklijas.info\/blog\/2018\/01\/01\/always-start-with-simple-solution\/","title":{"rendered":"Always start with simple solution (ConfigParser vs. JSON for Python configuration file)"},"content":{"rendered":"
Published on:<\/strong> 01.01.2018<\/p>\n Sometimes perfect is the enemy<\/a> of the good.<\/p>\n I had Python program<\/a>, that needed to access device via IP address<\/strong> and to do some diagnostic and commands on it.<\/p>\n At that time, I was accessing only one device (only one IP address).<\/p>\n But could see that in future (in few months to one year), I will need to do the same set of command on more devices.<\/p>\n One solution is to add IP address as a parameter to CLI program.<\/p>\n In my use case number of IP address that needs to be accessed will never be bigger than 34.<\/p>\n And writing 34 IP addresses as CLI parameter<\/strong>, that is around 373 letters<\/strong>, is not a nice solution.<\/p>\n When you need to read it, to see are all IP addressee included, it is not easy to read.<\/p>\n I was distributing my Python code as EXE<\/a>, so use of Python code as configuration was not possible.<\/p>\n Altho, I think that Python code as the configuration is a good solution if you are executing source code<\/strong>, and only developer (not average user who does not know what Notepad is) will edit it.<\/p>\n Sometimes I do have a problem that I tend to unnecessarily complicate things.<\/p>\n Because I think about all possible edge cases and all possible future uses.<\/p>\n And from these two, all possible future uses are the real problem<\/strong>.<\/p>\n Edge cases can happen, but is there a positive cost benefit to solve them and how?<\/p>\n This need to be determined on a case by case basis.<\/p>\n But “all possible future use” is trying to anticipate the future<\/strong>.<\/p>\n That is impossible<\/strong>.<\/p>\n From my experience, whenever I add code for future use cases, usually it was waste of time.<\/p>\n Even when I am the only user, so I can argue to my self that I know will need it.<\/p>\n Usually, I do not need it.<\/p>\n So, I have decided to eliminate waste<\/a> when developing software, starting from this project.<\/p>\n For example, here I needed a configuration file that will have a list of IP addresses, which I will iterate in This was the smallest requirement that I needed for my problem.<\/p>\n But immediately I was thinking that it would be nice to have:<\/p>\n And the list can go on.<\/p>\n But I said to myself, NO<\/strong>.<\/p>\n You will just make code that can read a list of items as a list in Python from the configuration file.<\/p>\n Nothing more.<\/p>\n If when you have the real need, you will add additional features when needed.<\/p>\n When I think about this, maybe this is an example of premature design<\/a>?<\/p>\n Premature design is deciding too early what a program should do.<\/strong><\/p>\n After investigating possible solution<\/a>, decision was to try ConfigParser<\/a>.<\/p>\n ConfigParser configuration file was:<\/p>\n Code was:<\/p>\n I found few problems with ConfigParser:<\/p>\n JSON configuration file was:<\/p>\n Code was:<\/p>\n There is much less code, and line count is important<\/strong>.<\/p>\n One thing that I did not like about JSON is I was hoping to get some more details, eg. what token in which line.<\/p>\n But you can not have it all<\/strong>, and ConfigParser was no bettter.<\/p>\n Decision was to use JSON as configuration file for Python, because<\/strong> code was less complicated (less lines of code<\/strong>).<\/p>\nConclusion<\/h4>\n
Why use configuration file<\/h4>\n
Python code as configuration was not possible<\/h4>\n
Sometimes perfect is enemy of good<\/h3>\n
for loop<\/code>.<\/p>\n
\n
192.168.1.1 --- 192.168.1.5<\/code>, and this can really get more complicated if you want to cover all edge cases.<\/li>\n
Why JSON is better than Configparser for list datatype<\/h4>\n
\n[other]\nlist_queue1 = [ \"192.168.1.34\", \"192.168.1.35\",\n 192.168.1.36,\n \"192.168.1.34\" ]\n<\/pre>\n
\nimport ConfigParser\nimport io\n\ndef get_as_list(text):\n _ = text.replace('[', '')\n _ = _.replace(']', '')\n _ = _.replace('\"', '')\n tmp_list = [ item.strip() for item in _.split(',') ]\n return tmp_list\n\ndef main():\n # Load the configuration file\n with open(\"config_ini.ini\") as f:\n sample_config = f.read()\n config = ConfigParser.RawConfigParser(allow_no_value=True)\n config.readfp(io.BytesIO(sample_config))\n\n # access them\n testing_1 = config.get('other', 'list_queue1')\n for item in get_as_list(testing_1):\n print item\n\nif __name__ == '__main__':\n main()\n<\/pre>\n
\n
\n
get_as_list()<\/code> function)<\/li>\n<\/ul>\n<\/li>\n
\"192.168.1.36\"<\/code> and
192.168.1.36<\/code> was both valid.\n
\n
Let try JSON (as configuration files in Python)<\/h4>\n
\n{\n \"test_list\":[\n \"test_1\",\n \"test_2\",\n \"test_3\"\n ]\n}\n<\/pre>\n
\nimport json\n\ndef main():\n with open('config_json.json') as json_data_file:\n data = json.load(json_data_file)\n\n for item in data['test_list']:\n print item\n\nif __name__ == '__main__':\n main()\n<\/pre>\n
\"ValueError: No JSON object could be decoded\"<\/code>, this is error message that you get if you JSON is invalid.<\/p>\n