Python CGI脚本被AJAX调用时找不到graphviz的twopi程序问题求助
我遇到了一个棘手的问题:Python脚本独立运行时一切正常,但作为CGI脚本被jQuery的$.ajax()调用时就会出错,恳请大家帮忙分析原因。
我在搭载macOS 11.6的新款MacBook Pro上本地开发Web应用,使用本地apache2服务器,已配置相关目录下的.py文件作为CGI程序运行。
本地开发环境配置
- 运行设备:新款MacBook Pro,系统版本macOS 11.6
- 已安装graphviz二进制文件路径:
/opt/homebrew/bin/twopi,版本为2.49.2 (20211016.1639) - pygraphviz版本:1.7
- Python版本:3.9.7,可执行文件路径为
/opt/homebrew/opt/python@3.9/bin/python3.9 - rdflib版本:
6.03a
该应用基于Python CGI脚本实现,核心功能为从本地文件系统读取数据,通过Python的requests模块从公网AllegroGraph实例拉取RDF数据,再通过graphviz和pygraphviz模块完成图布局生成可视化结果,最终在网页端展示。
核心代码
前端Ajax请求代码
function graphMe(charter){ $.ajax({ type: "get", url: "cartametallon.py", data: {"graphMe": charter}, dataType: 'json', success: deploySVG, error: function(jqXHR, textStatus, errorThrown) { console.log(jqXHR.response, textStatus, errorThrown); } }); }
后端CGI处理代码
import cgi, cgitb cgitb.enable(format="text") form = cgi.FieldStorage() try: if 'graphMe' in form: charter = form.getvalue('graphMe') uri = "<http://chartex.org/graphid/" + charter + ">" print ("Content-Type: application/json\r\n\r\n") print (json.dumps(visualizeDocumentGraph(uri))) except Exception: print ("Content-Type: text/plain\n") print("Exception in user code:") print("~"*20, __file__.split('/')[-1], "~"*20) traceback.print_exc(file=sys.stdout) print("~"*60)
visualizeDocumentGraph()函数会从多个来源组装图数据和元数据,存储为dict类型后序列化为JSON返回给前端,返回内容中包含由graphviz的twopi算法布局生成的SVG图字符串。目前已验证该Python函数所有逻辑均正常,命令行直接运行脚本可以返回预期结果,但通过jQuery.ajax()发起请求时收到如下报错:
报错详情
Content-Type: text/plain Exception in user code: ~~~~~~~~~~~~~~~~~~~~ cartametallon.py ~~~~~~~~~~~~~~~~~~~~ Traceback (most recent call last): File "/opt/homebrew/lib/python3.9/site-packages/pygraphviz/agraph.py", line 1344, in _get_prog runprog = self._which(prog) File "/opt/homebrew/lib/python3.9/site-packages/pygraphviz/agraph.py", line 1800, in _which raise ValueError(f"No prog {name} in path.") ValueError: No prog twopi in path. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "~/Sites/cartametallon/cartametallon.py", line 661, in <module> print (json.dumps(visualizeDocumentGraph(uri))) File "~/Sites/cartametallon/cartametallon.py", line 292, in visualizeDocumentGraph dgsvg = makedot(g).draw(format='svg', prog='twopi') File "/opt/homebrew/lib/python3.9/site-packages/pygraphviz/agraph.py", line 1596, in draw data = self._run_prog(prog, args) File "/opt/homebrew/lib/python3.9/site-packages/pygraphviz/agraph.py", line 1360, in _run_prog runprog = r'"%s"' % self._get_prog(prog) File "/opt/homebrew/lib/python3.9/site-packages/pygraphviz/agraph.py", line 1346, in _get_prog raise ValueError(f"Program {prog} not found in path.") ValueError: Program twopi not found in path.
目前的核心疑点是:CGI模式调用时提示找不到twopi程序,但脚本独立运行时完全正常。twopi二进制文件的安装路径为/opt/homebrew/bin/twopi,已经手动加入环境变量PATH,命令行查看PATH结果如下:
% echo $PATH ~/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
Python脚本也可以识别该路径,命令行运行时执行os.get_exec_path()结果如下:
>>> os.get_exec_path() ['~/opt/anaconda3/condabin', '/opt/homebrew/bin', '/opt/homebrew/sbin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin']
目前受该问题影响,Python脚本无法正常返回前端所需的JSON结果。正在重构升级的应用已经在线上正常运行,该应用近期刚迁移到A2 hosting服务商,调整配置后可以正常运行,但服务商预装的graphviz版本过旧,生成的可视化效果不符合需求,因此才进行本地重构。线上运行版本的环境配置如下:
线上运行环境配置
- graphviz版本:2.30.1 (20201013.1554)
- pygraphviz版本:1.5
- Python版本:2.7.18,运行于虚拟环境,编译信息为[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2
- RDFLib版本:5.0.0
恳请各位帮忙定位问题原因,多谢!
内容的提问来源于stack exchange,提问作者jjon

