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

ResourceWarning unclosed ssl.SSLSocket #87

Open
dbader opened this issue Sep 19, 2022 · 1 comment
Open

ResourceWarning unclosed ssl.SSLSocket #87

dbader opened this issue Sep 19, 2022 · 1 comment

Comments

@dbader
Copy link

dbader commented Sep 19, 2022

I'm getting a Python ResourceWarning when following the examples from the Customer.io Python docs:

ResourceWarning: unclosed <ssl.SSLSocket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('172.21.X.X', 57030), raddr=('35.227.X.X', 443)>
ResourceWarning: Enable tracemalloc to get the object allocation traceback

I believe the issue is that customerio.APIClient never closes the Requests Session object (see https://stackoverflow.com/questions/48160728/resourcewarning-unclosed-socket-in-python-3-unit-test). I couldn't find a documented method on APIClient to close the session either.

As a workaround, we can reach into the APIClient object and call .http.close() directly, but that seems brittle:

client = customerio.APIClient(CUSTOMERIO_APP_API_KEY)
request = customerio.SendEmailRequest(...)
client.send_email(request)
client.http.close()  # <-- manually close the session

Here's an idea of how this could work in the API client. It'd be nice if APIClient supported the Context Manager protocol, so that we could use it like this:

with customerio.APIClient(...) as client:
    client.send_email(...)

This relates to #27 and #31.

@dbader
Copy link
Author

dbader commented Sep 19, 2022

If anyone is looking for a workaround, I defined two wrapper classes adding the context manager methods:

class AppAPIClient(customerio.APIClient):
    def __init__(self):
        super().__init__(CUSTOMERIO_APP_API_KEY)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        self.http.close()


class TrackingAPIClient(customerio.CustomerIO):
    def __init__(self):
        super().__init__(
            CUSTOMERIO_TRACKING_API_SITE_ID,
            CUSTOMERIO_TRACKING_API_KEY,
        )

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        self.http.close()

So I can do the following:

with AppAPIClient() as client:
    client.send_email(...)

# and

with TrackingAPIClient() as client:
    client.identify(...)

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

No branches or pull requests

1 participant