Thu, Apr 18, 9:16 PM CDT

Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Mar 19 1:03 pm)

We now have a ProPack Section in the Poser FreeStuff.
Check out the new Poser Python Wish List thread. If you have an idea for a script, jot it down and maybe someone can write it. If you're looking to write a script, check out this thread for useful suggestions.

Also, check out the official Python site for interpreters, sample code, applications, cool links and debuggers. This is THE central site for Python.

You can now attach text files to your posts to pass around scripts. Just attach the script as a txt file like you would a jpg or gif. Since the forum will use a random name for the file in the link, you should give instructions on what the file name should be and where to install it. Its a good idea to usually put that info right in the script file as well.

Checkout the Renderosity MarketPlace - Your source for digital art content!



Subject: Transparent read of text and gzipped .duf(json) files


FVerbaas ( ) posted Mon, 06 December 2021 at 3:01 AM · edited Wed, 27 March 2024 at 11:09 PM
Forum Coordinator

Is there a simple method to let Python read a file, irrespective of it being gripped or not?

I am working on a small script that can read DS4 .duf pose files and apply the pose to a figure. It works great for .duf files in text format, but I found there also are .duf files in gzipped format. The file extension is the same.

I know gzip format can be detected and files can be opened for reading with gzip.open, but before I spend hours reinventing such a wheel I would like to know if there is a ready-to-call method to let Python handle deal with this transparently so my script can remain simple.

The .duf file content is of course  read via json.load().


adp001 ( ) posted Mon, 06 December 2021 at 4:39 AM

class gz_open(object):
    def __init__(self, fname, mode="r"):
        self.fname = fname
        self.mode = mode
        if "w" in mode:
            self.open = open
        else:
            import os
            if os.path.isfile(fname):
                with open(fname, 'rb') as f:
                    if f.read(2) != b'\x1f\x8b':
                        self.open = open
                    else:
                        import gzip
                        self.open = gzip.open
            else:
                raise FileNotFoundError("File '%s' not found." % fname)

    def __enter__(self):
        self._fh = self.open(self.fname, self.mode)
        return self._fh

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._fh.close()


if __name__ == "__main__":
    import json

    with gz_open("/home/fredi/Schreibtisch/DAZ_April.dbz", "r") as fh:
        js = json.load(fh)




adp001 ( ) posted Mon, 06 December 2021 at 5:29 AM

This can make it easier to deal with dictionaries:


class _dict(dict):
def __getattr__(self, key):
if key in self:
return self[key]
return self.__getattribute__(key)


if __name__ == "__main__":
import json

with gz_open("/home/fredi/Schreibtisch/DAZ_April.dbz", "r") as fh:
js = json.load(fh)
js =_dict(js)
print(js.version)

### "js.figures" is a list holding all defined figures.
### Each figure in the list is a dict.

fig = _dict(js.figures[0])
print(fig.name, fig.center_point, fig.end_point)




adp001 ( ) posted Mon, 06 December 2021 at 6:29 AM · edited Mon, 06 December 2021 at 6:32 AM

Dictionaries are nice. But sometimes one needs a "real" object. If this is the case, I use the following:


class obj_cls(object):
    pass


def obj_from_dict(d):
    obj = obj_cls()

    if isinstance(d, dict):
        for k, v in d.items():
            if isinstance(v, dict):
                setattr(obj, k, obj_from_dict(v))
            elif isinstance(v, (tuple, list)):
                setattr(obj, k, type(v)(_v if isinstance(_v, (int, float, str))
                                        else obj_from_dict(_v)
                                        for _v in v))
            else:
                setattr(obj, k, v)
        return obj
    elif isinstance(d, (list, tuple)):
        return type(d)(_d if isinstance(_d, (int, float, str))
                       else obj_from_dict(_d)
                       for _d in d)
    return d



Function "obj_from_dict(<dict>)" returns an object with all key/values set. The above looks like



    with gz_open("/home/fredi/Schreibtisch/DAZ_April.dbz", "r") as fh:
js = json.load(fh)
obj = obj_from_dict(js)
print(obj.version)

# "obj.figures" is a list holding all defined figures.
# Each figure in the list is an object (class obj_cls).

print(obj.figures[0].name, obj.figures[0].center_point, obj.figures[0].end_point)




adp001 ( ) posted Mon, 06 December 2021 at 7:19 AM · edited Mon, 06 December 2021 at 7:22 AM

And  little extension to get parts of the object as JSON:

class ObjEncoder(json.JSONEncoder):
    def default(self, obj):
        return obj.__dict__

# JSON method added to the class from above
class obj_cls(object):
    def as_json(self):
        return json.dumps(self.__dict__, indent=4, cls=ObjEncoder)


print(obj.figures[0].bones[0].as_json())


results in:

{
    "name": "hip",
    "center_point": [
        0.000440493,
        103.015,
        1.58171
    ],
    "end_point": [
        -0.0066126,
        86.7606,
        0.136487
    ],
    "orientation": [
        0,
        0,
        0,
        1
    ],
    "origin": [
        0.000440493,
        103.015,
        1.58171
    ],
...

}





adp001 ( ) posted Mon, 06 December 2021 at 9:20 AM · edited Mon, 06 December 2021 at 9:26 AM

Need to find id's in a DAZ file somewhere (recursiv)?  Try this extended obj_cls:

class obj_cls(object):
    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return self.id == other.id
        return False


    def as_json(self):
        return json.dumps(self.__dict__, indent=4, cls=ObjEncoder)

    def find_id(self, _id):
        if hasattr(self, "id") and self.id == _id:
            return self
        for v in self.__dict__.values():
            if isinstance(v, self.__class__):
                res = self.find_id(_id)
                if res:
                    return res
            elif isinstance(v, (tuple, list)):
                for entry in v:
                    if isinstance(entry, self.__class__):
                        res = entry.find_id(_id)
                        if res:
                            return res
        return None

---------------------------------------------------------------------------

with gz_open("/home/fredi/Schreibtisch/DAZ Gudrun.duf") as fh:
    obj = obj_from_dict(json.load(fh))

    part = obj.scene.find_id("Genesis8Female")
    print(part.label)
   




FVerbaas ( ) posted Mon, 06 December 2021 at 9:29 AM
Forum Coordinator

Hey. Thanks!

I had in the mean while found a solution that suits my needs. I open first as a gzip. That will give me an error when the file is not a gzip, so I can re-open in the error handling. 

Too bad though gzip.open does not do this internally.


# define a dict named 'data' at this level so it will survive the file with open.
data = {}
# Opening the chosen DUF file. It is JSON format so we use JSON package. In case of errors npars is set to 0, which
# will cut short the loop over the parameters and so effectively end the script except for the DrawAll()
# first attempt is to load from a gzipped, and on error load as a noncompressed file.
if len(duf) > 0:
    if duf.endswith('.duf'):
        with gzip.open(duf,'r') as f:
            try:
                data = json.load(f)
                try:
                    npars = len(data['scene']['animations'])
                except KeyError:
                    poser.DialogSimple.MessageBox('file does not contain pose data. \nNo pose loaded')
                    npars = 0
            except:
                with open(duf, 'r') as g:
                    try:
                        data = json.load(g)
                        try:
                            npars = len(data['scene']['animations'])
                        except KeyError:
                            poser.DialogSimple.MessageBox('file does not contain pose data. \nNo pose loaded')
                            npars = 0
                    except:
                        poser.DialogSimple.MessageBox('error loading file\nNo pose loaded')
    else:
        poser.DialogSimple.MessageBox('file '+ os.path.basename(duf) + ' is not a .duf file\nNo pose loaded')
        npars = 0
else:
    npars = 0


Privacy Notice

This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.