Using JSON to import data into a class

93 views
Skip to first unread message

David Martinez

unread,
Jun 18, 2014, 3:59:50 AM6/18/14
to python_in...@googlegroups.com
Hello,

As you might remember, a while ago I sent an email in which I was explaining how I wanted to create a schema for the projects at work. (Hopefully, I used the right word there). Since a lot of those projects are of the same type and they share not only data but behavior, I decided to create a class for them.

Initially, I was declaring paths manually as Instance attributes but you guys told me that I was better off storing that information in a file and then somehow importing it.

I've put together some code that reads JSON data from a file once the instance is initialized, and replaces the contents of __dict__ with the data retrieved from the file (A dictionary).

Code can be seen here:

    - https://gist.github.com/davidmartinezanim/0eddcecc4d141c8fa165


Do you think that this would be an acceptable approach to for the 'Project' classes?

The main reason why 'Project' is still a class is that all projects of this kind use the same functionality but there are other kinds of projects and I want them all to be children of a Project type. (Even though that the example above looks like a base class, it will be a concrete one inheriting from the base class instead of 'object')

Thanks in advance


--
David Martinez - Technical Animator
 

David Martinez

unread,
Jun 18, 2014, 6:58:19 AM6/18/14
to python_in...@googlegroups.com
I've just realized that replacing the contents of __dict__ with the data retrieved from the file might not be the best way to go since it will get rid of any of the instance attributes defined in the parent class.
So I've changed:

self.__dict__ = data

with

self.__dict__.update(data)

This seems to work nicely when it comes to avoid the issue. In any case, I'm still interested on hearing your thoughts about the approach.


Cheers,

Mark Jackson

unread,
Jun 18, 2014, 7:41:27 AM6/18/14
to python_inside_maya
Hi David,

we do a similar thing at work, on Maya boot we look at the users sandbox settings and what project they're working on, then bind that projects data to a global Projects object that all our code then uses for paths etc. It's a nice way to work as it means that project specific data is also bound and can be used where needed. We do some extra path logic so that in the project file itself we can do things like

build_path+asset/path/to/something

which is good as it allows extra path logic to be setup in the config file by the TD's rather than in code by the project object itself.

Mark


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/5a32b912-3d74-4980-b3bd-768bdc147b80%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
-------------------------------------
Mark Jackson
Technical Animation Director
http://markj3d.blogspot.com/

Eduardo Grana

unread,
Jun 18, 2014, 11:34:42 AM6/18/14
to python_in...@googlegroups.com
Hello David,

Maybe its not a great comment, but I would keep separated the 'settings' like
data = {'chars_folder': r'G:\TestProject\Source\Characters',
'renders_folder': r'G:\TestProject\Output\images',
'textures_folder': r'G:\TestProject\Resources\Images\Textures'}
from the functionality of saving data.
Then you can update both separately.
Maybe you can have and optional argument, and that data as default in a cascade fashion,
somthing like

# have default data in a separate file for example projectDefaults.py
data = {'chars_folder': r'G:\TestProject\Source\Characters',
'renders_folder': r'G:\TestProject\Output\images',
'textures_folder': r'G:\TestProject\Resources\Images\Textures'}

# then in the other file
import projectDefaults

def store_data_to_file(data=None):
  if data is None:
data = projectDefaults.data

Hope its usefull...
Eduardo



For more options, visit https://groups.google.com/d/optout.



--
Eduardo Graña
www.eduardograna.com.ar

Marcus Ottosson

unread,
Jun 23, 2014, 2:21:51 PM6/23/14
to python_in...@googlegroups.com

Hi David,

About injecting the contents of an external file into a class, I’d have to go with “its a bad idea”. The main and possibly only reason being the lack of feedback between the contents of the file and existing methods/properties of the class. I’m thinking you may one day extend your class with additional members which may either override previous ones from the file, or get overwritten sometime in the future by the next file.

I know object-oriented approaches rock and all, but have you considered not using a class for this?

import myio
myio.folder('chars')
myio.folder('renders')

mydata.get would then be reading from your external file directly (as opposed to being read upon instantiation) and either return a value or throw an error depending on what you’re looking for and it’d better follow the http://en.wikipedia.org/wiki/Open/closed_principle in that you could transparently append additional methods of reading data other than JSON and from disk, such as a database, as the only requirement would be a string key, as opposed to variables of a class which are both limited in which characters they may contain but also more lengthy to try/except

On another note, it seems you’re coding towards absolute paths, is this temporary? At the very least it could be helpful to store the root of paths within something more dynamic such as an environment variable so that you can work across OSs:

data = {'chars_folder': r'$ROOT\TestProject\Source\Characters',
        'renders_folder': r'$ROOT\TestProject\Output\images',
        'textures_folder': r'$ROOT\TestProject\Resources\Images\Textures'}

Additionally, it may also be helpful to store the information relative the directories you are referencing:

# $ROOT/TestProject/paths.json
{
    'Characters': 'Source/Characters',
    'Images': 'Output/images',
    'Textures': 'Resources/Images/Textures'
}

That way they’d stay portable across both platforms and projects, in case you’d prefer re-using the template/schema for others.




For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

David Martinez

unread,
Jun 25, 2014, 2:50:22 AM6/25/14
to python_in...@googlegroups.com
Thanks Mark, Eduardo and Marcus

Looks like I have some ideas to play with   :-)
I will try a few different things and let you know what my experiences are.

Cheers




--
David Martinez - Technical Animator
 


Reply all
Reply to author
Forward
0 new messages