I have written a small tool to generate a json file from sqlalchemy models files to automate the tedious procedure of writing all the sql raws in a json format. The script works, but there are few parts, see get_modules function, that can be improved. I would be glad to have a review of this code. Thanks
# -*- coding: utf-8 -*-
import os
import sys
import glob
PATH = sys.argv[1]
output_filename = 'en.json'
intro = ("""
{
"sidebar": {
"overview": "Overview",
},
"about": {
"title": "title"
},
"welcome": {
"title": "Welcome to the prototype app!"
},
""")
def get_fields(input_filename):
"""It returns all fields of a model in a list"""
fields = []
endpoint = None
with open(PATH+input_filename, 'r') as inputfile:
for line in inputfile:
if '__plural_name__' in line:
endpoint = line.split('=')[1].strip().replace("'","")
if '= Column' in line:
fields.append(line.split()[0])
return endpoint, fields
def get_modules():
"""It returns a list of all models"""
files = []
cwd = os.getcwd()
os.chdir(PATH)
files = glob.glob("*.py")
os.chdir(cwd)
return files
if __name__ == "__main__":
models = get_modules()
target = open(output_filename, 'w')
target.write(intro)
for m in models:
if m != '__init__.py':
end_name, attrs = get_fields(m)
target.write(' "{}": {{\n'.format(end_name))
target.write(' "title": "{}",\n'.format(end_name))
target.write(' "fields": {\n')
for a in attrs:
target.write(' "{}": "{}",\n'.format(a,a))
target.write(' }\n')
target.write(' },\n')
target.close()
1 Answer 1
You should take advantage of what is already available. For example, the json
module. Instead of putting the string together manually, use json.dumps
. Python doesn't have a SQLAlchemy library built-in, but you can get one on PyPI, just pip install SQLAlchemy
. Using this, you can browse https://stackoverflow.com/q/5022066/5827958 to see some simple ways of converting SQLAlchemy to JSON.
You define files = []
in get_modules()
. That's unnecessary. Python does not need you to declare variables before using them. Just save yourself that tiny bit of processing time, and take it out.
You can also make use of os.path
, a built-in pointer to an OS-specific filesystem path module. In get_modules()
, you can simplify down to:
def get_modules():
return glob.glob(os.path.join(PATH, "*.py"))
Since that now returns an absolute path instead of a relative one, you can now use merely input_filename
instead of PATH+input_filename
in get_fields()
.
I would also define get_modules
as taking an argument for its path. That way, an importing module can use it for whatever path it wants, but your if __name__ == '__main__'
block will give it sys.argv[1]
. Since I just changed your function to using absolute paths, get_fields()
doesn't need to know about PATH
at all. On the side, you shouldn't be reading sys.argv
unless __name__ == '__main__'
anyway.
The purpose of your file is to convert, but an importing module has no access to the conversion code. I would suggest defining a function for the conversion, and then let the if __name__ == "__main__"
block call that function with sys.argv[1]
as an argument.
I'm glad that you use a with
block in get_fields()
, but I see you aren't in your main code. This could cause unexpected problems if something unexpected happened. You should open a file without a with
block only in very rare cases.
-
\$\begingroup\$ thanks a lot for your review. It is really helpful. I will first try to adjust my code, then look at other examples to convert sqlalchemy into json and see if I can use them for what I need \$\endgroup\$diegus– diegus2017年04月12日 19:28:37 +00:00Commented Apr 12, 2017 at 19:28