pythoncgi交互找不到graphviz程序twopi
python cgi interaction fails to find graphviz program twopi
我有一个令人抓狂的错误,我的 python 脚本在 运行 独立执行某些操作时成功,但在 运行 作为由 [=89= 调用的 cgi 脚本时失败]的$.ajax()
。欢迎任何见解。
我正在使用本地 apache2 服务器在我的新 MacbookPro (macOS 11.6) 上本地开发此 Web 应用程序,我已将其配置为 运行 相关目录中的 .py 文件作为 cgi 程序。
相关的工作部分是这些:
- 本地在我的新 MacbookPro (macOS 11.6)
- graphviz 二进制文件已安装:/opt/homebrew/bin/twopi:
twopi - graphviz 版本 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 从本地文件系统检索一些数据,并从 Web 上的 AllegroGraph 实例检索一些 RDF 数据的 requests
模块,然后使用 graphviz 和 python 的 pygraphviz 模块在网页中布局和显示图形可视化。
javascript 发出这样的 GET 请求:
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);
}
});
}
python cgi 脚本使用 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
中,然后应将其 return 作为 [=90= 编辑到引用页面] 目的。该对象中存储的内容之一是图形的 SVG 字符串,由 graphviz 的 twopi
算法布局。我已经验证此 python 函数的每个元素都按预期工作,并且当在命令行 运行 时,它 return 是预期的对象;但是,对 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
程序,但是 运行 本身,我的 python 脚本没有问题。 twopi
二进制文件安装在 /opt/homebrew/bin/twopi
,可通过环境变量 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()
['~/opt/anaconda3/condabin', '/opt/homebrew/bin', '/opt/homebrew/sbin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin']
我无法将我的 python 脚本转换为 return 我需要的 json 网页,哎呀!由于我正在尝试做的是重构和更新 运行 在 https://neolography.com/chartex/ 上很好的现有应用程序,这让这变得更加令人抓狂。这个工作程序最近被转移到一个新的网络主机上,需要稍微修改一下才能让它再次工作,而且图形输出不如我的旧主机,因为 A2 主机坚持安装旧版本的 graphviz(不要'任务)。因此,该工作程序的相关工作部分是:
- twopi - graphviz 版本 2.30.1 (20201013.1554)
- pygraphviz 1.5
- Python 2.7.18(默认,2021 年 7 月 8 日,01:00:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] 在 linux2
(这个 python 必须 运行 在虚拟环境中安装,这样我才能安装它:)
- RDFLib 版本:5.0.0
我花了几天时间,但多亏了 Thomas 的评论,一些观察 here, and the docs for the python os module 本身,我终于明白了“PATH”环境变量,当我 运行 一个脚本在命令行,与正在执行的 cgi 程序上下文中的相同变量完全不同。
% echo $PATH
~/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
和
>>> os.environ["PATH"]
'~/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
与 os.environ["PATH"]
不同,当它被 apache 引用时 运行 是 cgi 脚本。
更糟糕的是,我将 $PATH 变量与 python 的 sys.path
混为一谈,后者的目的完全不同。我的 cgi 程序,使用 pygraphviz,试图执行 twopi
,一个位于 /opt/homebrew/bin
的二进制文件,在执行 cgi 程序的上下文中,它可用的 PATH 变量如下所示:
"/usr/bin:/bin:/usr/sbin:/sbin:"
在 cgi 程序中向该变量添加必要的路径很容易,如下所示:
os.environ["PATH"] = f"{os.environ['PATH']}:/opt/homebrew/bin"
这解决了我的问题。可是,我还是不放心。这似乎是一种骇人听闻的方法。我仍然不完全理解为什么 apache 的 PATH
不同于 python 解释器可用的 $PATH
,或者在命令行的脚本 运行 中。我收集到 cgi 程序可用的 PATH
是不同的,因为 apache 以不同的用户身份执行它 (_www
)。
最好知道是否有更规范的方法来解决这个问题。我们将不胜感激地收到有关文档的任何建议,以澄清我对此问题的理解。
我有一个令人抓狂的错误,我的 python 脚本在 运行 独立执行某些操作时成功,但在 运行 作为由 [=89= 调用的 cgi 脚本时失败]的$.ajax()
。欢迎任何见解。
我正在使用本地 apache2 服务器在我的新 MacbookPro (macOS 11.6) 上本地开发此 Web 应用程序,我已将其配置为 运行 相关目录中的 .py 文件作为 cgi 程序。
相关的工作部分是这些:
- 本地在我的新 MacbookPro (macOS 11.6)
- graphviz 二进制文件已安装:/opt/homebrew/bin/twopi:
twopi - graphviz 版本 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 从本地文件系统检索一些数据,并从 Web 上的 AllegroGraph 实例检索一些 RDF 数据的 requests
模块,然后使用 graphviz 和 python 的 pygraphviz 模块在网页中布局和显示图形可视化。
javascript 发出这样的 GET 请求:
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);
}
});
}
python cgi 脚本使用 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
中,然后应将其 return 作为 [=90= 编辑到引用页面] 目的。该对象中存储的内容之一是图形的 SVG 字符串,由 graphviz 的 twopi
算法布局。我已经验证此 python 函数的每个元素都按预期工作,并且当在命令行 运行 时,它 return 是预期的对象;但是,对 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
程序,但是 运行 本身,我的 python 脚本没有问题。 twopi
二进制文件安装在 /opt/homebrew/bin/twopi
,可通过环境变量 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()
['~/opt/anaconda3/condabin', '/opt/homebrew/bin', '/opt/homebrew/sbin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin']
我无法将我的 python 脚本转换为 return 我需要的 json 网页,哎呀!由于我正在尝试做的是重构和更新 运行 在 https://neolography.com/chartex/ 上很好的现有应用程序,这让这变得更加令人抓狂。这个工作程序最近被转移到一个新的网络主机上,需要稍微修改一下才能让它再次工作,而且图形输出不如我的旧主机,因为 A2 主机坚持安装旧版本的 graphviz(不要'任务)。因此,该工作程序的相关工作部分是:
- twopi - graphviz 版本 2.30.1 (20201013.1554)
- pygraphviz 1.5
- Python 2.7.18(默认,2021 年 7 月 8 日,01:00:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] 在 linux2
(这个 python 必须 运行 在虚拟环境中安装,这样我才能安装它:) - RDFLib 版本:5.0.0
我花了几天时间,但多亏了 Thomas 的评论,一些观察 here, and the docs for the python os module 本身,我终于明白了“PATH”环境变量,当我 运行 一个脚本在命令行,与正在执行的 cgi 程序上下文中的相同变量完全不同。
% echo $PATH
~/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
和
>>> os.environ["PATH"]
'~/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
与 os.environ["PATH"]
不同,当它被 apache 引用时 运行 是 cgi 脚本。
更糟糕的是,我将 $PATH 变量与 python 的 sys.path
混为一谈,后者的目的完全不同。我的 cgi 程序,使用 pygraphviz,试图执行 twopi
,一个位于 /opt/homebrew/bin
的二进制文件,在执行 cgi 程序的上下文中,它可用的 PATH 变量如下所示:
"/usr/bin:/bin:/usr/sbin:/sbin:"
在 cgi 程序中向该变量添加必要的路径很容易,如下所示:
os.environ["PATH"] = f"{os.environ['PATH']}:/opt/homebrew/bin"
这解决了我的问题。可是,我还是不放心。这似乎是一种骇人听闻的方法。我仍然不完全理解为什么 apache 的 PATH
不同于 python 解释器可用的 $PATH
,或者在命令行的脚本 运行 中。我收集到 cgi 程序可用的 PATH
是不同的,因为 apache 以不同的用户身份执行它 (_www
)。
最好知道是否有更规范的方法来解决这个问题。我们将不胜感激地收到有关文档的任何建议,以澄清我对此问题的理解。