使用大型 networkx 图形和 Flask 网络服务器
Working with large networkx graph and Flask webserver
我正在尝试创建一个可以查询 NetworkX 图的 Flask 网络应用程序,return 最短路径(使用 Dijkstra 的算法,加上 Yen 的 k 最短路径算法)。
这是我的示例代码(去掉了错误处理 等 ,只显示了 Dijkstra 实现),如果您提交一个 return 路径GET 请求 localhost:3000/d?source=a&target=b
:
import csv
import json
import networkx as nx
from flask import Flask, request
app = Flask(__name__)
G = nx.Graph()
@app.route('/d')
def dijkstra():
global G
source = request.args['source'].lower().strip()
target = request.args['target'].lower().strip()
path = nx.dijkstra_path(G, source, target, weight='weight')
return json.dumps(path)
if __name__ == '__main__':
global G
with open('nodes.csv', 'rb') as f:
reader = csv.reader(f)
node_list = list(reader)
for i in nodes:
G.add_node(i[0])
with open('edges.csv', 'rb') as f:
reader = csv.reader(f)
edge_list = list(reader)
for i in edges:
G.add_edge(i[0], i[1], weight=i[2])
app.run(host='0.0.0.0', port=3000, use_reloader=False)
图表非常大(一百万个节点,两千万条边),所以我目前在应用程序加载时从 CSV 填充它,而不是为每个请求构建它。在我的 MacBook Pro(3GHz,16GB 内存)本地 运行 上,这大约需要五分钟。查找需要不同的时间,但通常在 15 秒左右,并且性能通常会在使用一定量后下降,这意味着我必须重新启动应用程序。
问题一:因为这很慢而且占用大量内存,有没有办法存储这个图,这样我就不必每次都生成它,然后等一下它在内存中?
问题二:我使用 G
作为全局变量的方法是否正确?
我以前没有用过这么大的图表,所以我知道我的实现可能远非理想,如果有任何关于如何使它可靠地执行 better/more 的想法,我将不胜感激!
您是否尝试过使用市场中可用的缓存?
- Flask Cache 这个库利用了 redis 缓存
- Redis Cache
- 或者您甚至可以使用 Python Pickles
创建一个更新这些缓存或 pickle 的后台脚本,您的请求仅加载并发送其中的数据。
编辑
由于 OP 还在 NetworkX 上找到了 Builtin Pickles Method
enter link description here
比较酸洗和直接处理CSV的速度
编辑 2
当您 pickle 整个数据结构时,您会受到系统 RAM 的限制。但是,您可以分块进行。
streaming-pickle 可以作为酸洗大于板上内存的对象的解决方案。因为 unpickling 时会出现问题,但您也可以使用这种方法来克服它。
或者使用 Redis 方法,如果你想在请求完成后保留数据,你可以寻找 Redis Cluster
这是一个非常棘手的问题 :D 取决于您实际需要什么。
我正在尝试创建一个可以查询 NetworkX 图的 Flask 网络应用程序,return 最短路径(使用 Dijkstra 的算法,加上 Yen 的 k 最短路径算法)。
这是我的示例代码(去掉了错误处理 等 ,只显示了 Dijkstra 实现),如果您提交一个 return 路径GET 请求 localhost:3000/d?source=a&target=b
:
import csv
import json
import networkx as nx
from flask import Flask, request
app = Flask(__name__)
G = nx.Graph()
@app.route('/d')
def dijkstra():
global G
source = request.args['source'].lower().strip()
target = request.args['target'].lower().strip()
path = nx.dijkstra_path(G, source, target, weight='weight')
return json.dumps(path)
if __name__ == '__main__':
global G
with open('nodes.csv', 'rb') as f:
reader = csv.reader(f)
node_list = list(reader)
for i in nodes:
G.add_node(i[0])
with open('edges.csv', 'rb') as f:
reader = csv.reader(f)
edge_list = list(reader)
for i in edges:
G.add_edge(i[0], i[1], weight=i[2])
app.run(host='0.0.0.0', port=3000, use_reloader=False)
图表非常大(一百万个节点,两千万条边),所以我目前在应用程序加载时从 CSV 填充它,而不是为每个请求构建它。在我的 MacBook Pro(3GHz,16GB 内存)本地 运行 上,这大约需要五分钟。查找需要不同的时间,但通常在 15 秒左右,并且性能通常会在使用一定量后下降,这意味着我必须重新启动应用程序。
问题一:因为这很慢而且占用大量内存,有没有办法存储这个图,这样我就不必每次都生成它,然后等一下它在内存中?
问题二:我使用 G
作为全局变量的方法是否正确?
我以前没有用过这么大的图表,所以我知道我的实现可能远非理想,如果有任何关于如何使它可靠地执行 better/more 的想法,我将不胜感激!
您是否尝试过使用市场中可用的缓存?
- Flask Cache 这个库利用了 redis 缓存
- Redis Cache
- 或者您甚至可以使用 Python Pickles
创建一个更新这些缓存或 pickle 的后台脚本,您的请求仅加载并发送其中的数据。
编辑 由于 OP 还在 NetworkX 上找到了 Builtin Pickles Method enter link description here
比较酸洗和直接处理CSV的速度
编辑 2 当您 pickle 整个数据结构时,您会受到系统 RAM 的限制。但是,您可以分块进行。
streaming-pickle 可以作为酸洗大于板上内存的对象的解决方案。因为 unpickling 时会出现问题,但您也可以使用这种方法来克服它。
或者使用 Redis 方法,如果你想在请求完成后保留数据,你可以寻找 Redis Cluster
这是一个非常棘手的问题 :D 取决于您实际需要什么。