Question

I am wondering if there is a way to have a python variable to behave like a python module.

Problem I currently have is that we have python bindings for our API. The bindings are automatically generated through swig and to use them someone would only needs to:

import module_name as short_name

short_name.functions()

Right now we are studying having the API to use Apache Thrift. To use it someone needs to:

client, transport = thrift_connect()

client.functions()
...    

transport.close()

Problem is that we have loads of scripts and we were wondering if there is a way to have the thrift client object to behave like a module so that we don't need to modify all scripts. One idea we had was to do something like this:

client, transport = thrift_connect()

global short_name
short_name = client
__builtins__.short_name = client

This 'sort of' works. It creates a global variable 'short_name' that acts like a module, but it also generates other problems. If other files import the same module it is needed to comment those imports. Also, having a global variable is not a bright idea for maintenance purposes.

So, would there be a way to make the thrift client to behave like a module? So that people could continue to use the 'old' syntax, but under the hood the module import would trigger a connection ans return the object as the module?

EDIT 1:

It is fine for every import to open a connection. Maybe we could use some kind of singleton so that a specific interpreter can only open one connection even if it calls multiple imports on different files.

I thought about binding the transport.close() to a object termination. Could be the module itself, if that is possible.

EDIT 2:

This seems to do what I want:

client, transport = thrift_connect()
attributes = dict((name, getattr(client, name))  for name in dir(client)  if not (name.startswith('__') or name.startswith('_')))
globals().update(attributes)
Was it helpful?

Solution

Importing a module shouldn't cause a network connection.

If you have mandatory setup/teardown steps then you could define a context manager:

from contextlib import contextmanager

@contextmanager
def thrift_client():
    client, transport = thrift_connect()
    client.functions()
    try:   
        yield client
    finally:
        transport.close()

Usage:

with thrift_client() as client:
    # use client here

In general, the auto-generated module with C-like API should be private e.g., name it _thrift_client and the proper pythonic API that is used outside should be written on top of it by hand in another module.

To answer the question from the title: you can make an object to behave like a module e.g., see sh.SelfWrapper and quickdraw.Module.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top