plpython3: can a function return a 'class' or 'generator' object to a query

87 views Asked by At

I am running a docker container with a postgres image. The image includes python3, pandas, and networkx. The combination allows me to construct a graph from the db data all within the postgres environment.

I want to be able to retrieve the graph through a remote query to the db. The graph exists as an entry in the GD with type class. If I return it as type text as in the code below, I get the string Graph with 40 nodes and 20 edges.

drop function if exists GD_retrieve();
create or replace function GD_retrieve()
    returns text
language plpython3u as
$function$
    return GD['recon_G']
$function$;

select * from GD_retrieve();

I thought maybe running a conversion to text might work e.g. convert the graph to graphml (a text format) and return that as a generator.

drop function if exists GD_retrieve();
create or replace function GD_retrieve()
    returns text
language plpython3u as
$function$
    import networkx as nx
    graphml = nx.generate_graphml(GD['recon_G'])
    return graphml
$function$;

That gives a string '<generator object generate_graphml at 0x7fe78b6b2480>' but if I use the cytoscape format:

drop function if exists GD_retrieve();
create or replace function GD_retrieve()
    returns text
language plpython3u as
$function$
    import networkx as nx
    graph_cyto = nx.cytoscape_data(GD['recon_G'])
    return graph_cyto
$function$;

I get a very long string containing all the data that can be parsed or imported in to networkx locally or into cytoscape itself. Not awful but not elegant. Is there a better way to do this?

1

There are 1 answers

0
MikeB2019x On BEST ANSWER

Another way is to do this:

drop function if exists GD_retrieve();
create or replace function GD_retrieve()
    returns text[]
language plpython3u as
$function$
    import networkx as nx
    graph = GD['recon_G']  <-- networkx graph stored in global dict
    graph_alt = nx.generate_graphml(graph)  <-- returns a generator
    graphml_ser = []
    for item in graph_alt:
        graphml_ser.extend([item]) <-- use generator to build up a long string
    return graphml_ser  <-- returns a text array 
$function$;

So if I send a query select * from GD_retrieve(); I get back a graphml string of text, essentially a serialized XML file with elements specifically related to graphs. Again not elegant but it works.