Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is calling __init__ from __new__ in OWSLib/owslib/feature/wfs110.py necessary? #520

Closed
vjf opened this issue Oct 8, 2018 · 5 comments
Closed

Comments

@vjf
Copy link
Contributor

vjf commented Oct 8, 2018

I have been trying to 'pickle' instances of "WebFeatureService_1_1_0", but this is difficult because the code calls __init__ from within __new__.

When unpickling the object, 'pickle' calls __new__ to create the instance

(From https://docs.python.org/3/library/pickle.html#pickling-class-instances)

def load(cls, attributes):
obj = cls.__new__(cls)
obj.__dict__.update(attributes)
return obj

then because this calls __init__, it tries to fully re-create the object, which makes the use of pickle pointless!

In the end, I had to override WebFeatureService_1_1_0.__new__ with one that does not call __init__ to get pickle to work.

Also I understand that python calls __new__ then calls __init__ when creating objects, (https://docs.python.org/3/reference/datamodel.html#object.__new__)

This means that __init__ is called twice!

Is this a bug, or is there a good reason for calling __init__ from within __new__?

If it is a bug, I'd be happy to submit a pull request for this and the other WFS versions.

Copy link

github-actions bot commented Oct 6, 2024

This Issue has been inactive for 90 days. In order to manage maintenance burden, it will be automatically closed in 7 days.

@github-actions github-actions bot added the stale label Oct 6, 2024
Copy link

This Issue has been closed due to there being no activity for more than 90 days.

@geographika
Copy link
Contributor

Resolved with #548

@geographika
Copy link
Contributor

@vjf - do you have an example of pickling the WFS class? I get errors as lxml classes can't be pickled:

import pickle
from owslib.wfs import WebFeatureService

wfs_url = "https://demo.mapserver.org/cgi-bin/wfs?"
wfs = WebFeatureService(url=wfs_url, version="2.0.0")

with open("wfs_object.pkl", "wb") as f:
    pickle.dump(wfs, f)
    # TypeError: cannot pickle 'lxml.etree._Element' object

Just wondering what approach you used (the dill library also fails).

@vjf
Copy link
Contributor Author

vjf commented Jan 31, 2025

@geographika

It was a long time ago, I think I was using 'diskcache'

This will fail with a TypeError when calling 'pickle.load()' if OWSLib < v0.32.1:

from owslib.wfs import WebFeatureService
from diskcache import Cache
import copyreg
from lxml import etree

wfs_url = "https://demo.mapserver.org/cgi-bin/wfs?"
wfs_dk = WebFeatureService(url=wfs_url, version="2.0.0")


def element_unpickler(data):
    return etree.fromstring(data)

def element_pickler(element):
    data = etree.tostring(element)
    return element_unpickler, (data,)

copyreg.pickle(etree._Element, element_pickler, element_unpickler)

def elementtree_unpickler(data):
    data = StringIO(data)
    return etree.parse(data)

def elementtree_pickler(tree):
    data = StringIO()
    tree.write(data)
    return elementtree_unpickler, (data.getvalue(),)

copyreg.pickle(etree._ElementTree, elementtree_pickler, elementtree_unpickler)


cache = Cache()
key = cache.push(wfs_dk)
print(cache.pop(key))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants