2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案)
2021-07-15 06:15
标签:需要 value options OLE rom svc 并且 har compiler 可以负责任的说,这篇文档是windows10安装pygraphviz中,在中文技术网站中最新的文档,没有之一。是自己完全结合各种问题,包括调试等,总结出来的。 问题来源:主要是可视化RvNN网络的树结构。 pygraphviz安装时,我参考了博文http://www.myexception.cn/perl-python/2046792.html。但是,文章的解决方案已经失效。 站在巨人的肩膀上。 前述作者在上述博文链接中阐述,windows10下安装pygraphviz要去http://www.lfd.uci.edu/~gohlke/pythonlibs/的地址下载python packages在windows平台上的安装包。 但是,现在这个资源已经404. 其提供的过程就是:先安装graphviz,然后使用如下命令安装pygraphviz 很遗憾,虽然网上没有这些资源了,我在csdn上还是找到了如下版本: 可惜,python是3.6,使用这个,依旧安装失败。
因为只在python3.4版本上才能使用。 先安装graphviz-2.38.msi文件。是官网上的。 去官网下载代码。 https://github.com/pygraphviz/ 直接python setup.py install,会报出找不到vc14版本的相关错误。 但是信息不够详细。于是,spyder带参数install调试setup.py程序,看究竟是哪一步出了问题。 在spyder console键入:
然后一直跟踪到出错的位置: 调试pygraphviz的setup.py 并且带参数”install” 调试,以后发现,其出错函数在这里: 执行以后会提示: 那么对于这个函数,里面有这样一段说明: Microsoft Visual C++ 14.0: Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) Microsoft Visual Studio 2017 (x86, x64, arm, arm64) Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) 也就是说:安装对应的即可。 找到了相应的Microsoft Visual C++ 14.0 builder的生成器。但是由于我的电脑安装了vs2015,因此产生冲突。所以,我升级visual studio为2017版本。下载界面在: https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=Professional&rel=15&rr=https%3A%2F%2Fdocs.microsoft.com%2Fzh-cn%2Fvisualstudio%2Freleasenotes%2Fvs2017-relnotes# def msvc14_get_vc_env(plat_spec): """ Patched "distutils._msvccompiler._get_vc_env" for support extra compilers. Set environment without use of "vcvarsall.bat". Known supported compilers ------------------------- Microsoft Visual C++ 14.0: Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) Microsoft Visual Studio 2017 (x86, x64, arm, arm64) Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) Parameters ---------- plat_spec: str Target architecture. Return ------ environment: dict """ # Try to get environment from vcvarsall.bat (Classical way) try: return get_unpatched(msvc14_get_vc_env)(plat_spec) except distutils.errors.DistutilsPlatformError: # Pass error Vcvarsall.bat is missing pass # If error, try to set environment directly try: return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() except distutils.errors.DistutilsPlatformError as exc: _augment_exception(exc, 14.0) raise 因此,下载Microsoft Visual C++ 14.0并且安装。但是提示Visual studio2015版本和它不兼容。于是,又升级2015版本到2017版本,然后再执行这个程序。成功。这个程序我是从csdn上下载的,后续会放到本文末尾的附件链接当中。 pygraphviz/graphviz_wrap.c(2987): fatal error C1083: Cannot open include file: ‘graphviz/cgraph.h‘: No such file or directory 此时,修改setup.py文件,添加如下代码。这是因为pygraphviz要对一个graphviz_wrap.c文件进行编译,因此就要设置头文件和库文件的包含路径。 注意,实际lib是在release下。 虽然添加了头文件路径和库文件路径,但是会提示无法打开lib文件。 我们发现,错误是在执行running build_ext时,注意,ext就是extension的意思,也就是在python程序中调用编译器编译C语言的相关文件。 可以看到:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe对文件进行编译的时候,里面已经添加了"-IC:\Program Files (x86)\Graphviz2.38\include"的头文件路径,解决了之前头文件缺失的问题。 但是,在执行后续C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe 但是,修改setup.py文件时添加的include_dirs=[‘C:\Program Files (x86)\Graphviz2.38\include‘] 确实生效了。 为什么在setup.py中添加library_dirs之后,再调用VC的链接程序,并没有向指定库文件路径下寻找cdt.lib呢? 这是问题的根本所在。启动调试进程,调试setup.py文件。在spyder的console端键入如下: 跟踪上图中setup函数中的执行,尤其是对ext_modules的数据处理。跟踪这个数据处理,就能找到哪里引用了include_dirs,哪里引用了library_dirs。 数据就是通道 我们需要找到输出异常的位置,离它越近越好,就像逼近真相。 查看出错时的输出信息,有如下最关键的地方: 然后跟踪程序执行,会在python的系统文件dist.py中有run_commands的函数 这里面就有running %s的输出。那么我相信关键进程就在cmd_obj.run()中。正是这个执行过程,里面出错。 所以,log.info处下断点,当输出running buid_ext之后,进入run的函数内部:run内部又会跟进到了build_ext.py文件的核心函数run中: 里面会对compiler编译器进行设置,一直到执行self.build_extensions函数。 跟入该函数, 然后,在console端调试: 这里面的extension的命名“pygraphviz._graphviz”和setup.py文件中指定的命名是一致的。 也就是说,到目前为止: 已经找到了对setup.py文件中extension进行处理的核心代码,继续跟踪就会知道library_dirs为什么会失效。 跟踪进入cython_sources函数,就会看到:sources在第一个for循环中正是extension除去名称之后的第一行。 我们在cython_sources中下断点,直到sources是library-dirs的那一行。 可惜,直接一次循环就报出了本文所出现的link.exe链接的错误。 于是,直接跟入build_extension函数,就第一次循环就跟进去:如下, 我们输出可以看到: 我们跟进compile函数,确实没有给library_dirs进行赋值的选项。 继续跟,跟完compile以后,发现compile只是进行了编译操作。 会输出: ipdb> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD "-IC:\Program Files (x86)\Graphviz2.38\include" -IC:\ProgramData\Anaconda3\include -IC:\ProgramData\Anaconda3\include "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\8.1\include\shared" "-IC:\Program Files (x86)\Windows Kits\8.1\include\um" "-IC:\Program Files (x86)\Windows Kits\8.1\include\winrt" /Tcpygraphviz/graphviz_wrap.c /Fobuild\temp.win-amd64-3.6\Release\pygraphviz/graphviz_wrap.obj 现在,继续在build_extension中跟入: 这个就是链接过程。也就是在python程序中调用c编译器编译c目标程序时,会执行的函数。 我们跟进去。 ipdb> print (ext.library_dirs) 这也说明,确确实实是传入进去了。我们进入这个函数: 一直跟到里面的一个link函数时,我们发现有问题! 也就是,传入的library_dirs已经变成了 C:\Program Files (x86)\Graphviz2.38\lib elease\lib 这是什么鬼!!! 里面有一个_fix_lib_args的操作,但是可以看到: lib路径已经错了。本来应该是lib\\release\lib的,却变成了libelease\lib了。 然后一直进入到: self.spawn([self.linker] + ld_args) 我们可以输出如下: 结果这里面输出的ld_args竟然是: C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib‘ 千万不要以为是正确的地址。正确的是C:\\Program Files (x86)\\Graphviz2.38\\lib\\release\\lib。 我们来观察一下: ld_args = (ldflags + lib_opts + export_opts + objects + [‘/OUT:‘ + output_filename]) 然后ld_args是: 猛地一看,还是错误的。为什么在console端用print(ld_args )输出的是: C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib‘ 这是因为,你没有双击开。你双击开看到的是: 看到了吗?这是windows下的换行符号\r。在控制台输出的时候变成了\r。 在spyder中查看的时候,是换行。 而实际上: 目前为止,真正传入的就是这么个玩意: /LIBPATH:C:\Program Files (x86)\Graphviz2.38\lib elease\lib 也就是说,是换行符号\r。 我们双击点开libopts也是一样的。libopts是构成ld_args的重要组成。所以,后面的就不用跟了。 link程序必然出错。因为找不到cdt.lib文件。所以,link.exe程序必然失败,报出1181错误。 现在已经知道怎么改了,就是把setup.py中路径的反斜杠,全部改为斜杠。但是我不能容忍不知道为什么传递的时候出错。 我们会发现是在调用link_shared_object的时候出的错误: 此时调试输出的是: 当跟入函数以后: 所以,错误就是ext.library_dirs生成的过程出错。 那么就要追踪ext.library_dirs是如何依据setup.py文件中的extension项目生成的。 所以,关键是找到调用build_extension函数的地方,并且看是谁把值传入了ext。 现在开始倒推: 在进入这个函数的时候,输出仍然是: 所以,错误就在于生成self.extensions的过程中就已经注定了。 那么什么时候生成self.extensions的呢? 我们进入check_extensions_list函数,仍旧是输出的是错误的地址。 所以,错误的形成不是在build_extensions中。 而是在调用build_extensions之前,然后生成了self.extensions,里面包含了‘扭曲"的地址。 那么就是build_ext类的问题了,因为它就是那个self。 我们通过观察build_ext的类结构,和快速的扫描代码,找到了。 它的finalize_options函数中对self.extensions进行了设置。 这个时候,刚刚执行完下面代码: 我们就在console端键入: 可以看出,已经错了。所以,错误的形成不是在self.extensions的生成中。 而是在self.distribution.ext_modules的生成中。于是,进一步倒推。 在build_ext中,并不能找到self.distribution的相关代码。我们发现,build_ext继承的是Command类。Command类中有self.distribution。 所以,我们就要关注于build_ext这个类对象的生成。 这个时候,就要重头开始调试,看哪个地方生成了build_ext这个类的对象引用。 肯定是在上面的三行代码中,完成了对build_ext类的生成,在这里完成了对self.distribution的操作。 首先跟入get_command_obj函数,感觉这个是最有可能对Command子类build_ext类对象的生成过程。因为从名字来看就是get_command_obj,并且注释是: 执行完第一行程序: 由于之前是有: 所以我们直接在调试console输入: 结果发现:名称已经出错了!!! 那么问题肯定是在self.command_obj.get中了!!!它在生成build_ext类对象的时候,初始化父类Command的distribution成员时,就已经把地址”扭曲“了!!! 最遗憾的是!!!这个self.command_obj.get压根跟入不进去。很有可能代码不是开源的,只是作为功能提供在链接库当中。所以,这是一个bug。 什么bug??? 就是在setup.py文件中的extension中写入library_dirs的时候,如果传入如下的地址: 那么出于某种原因,python系统,会将\r看作换行符。因此,在转变的过程中: 本来是要将\处理成\\的,但是这个\r被遗漏了。于是就产生了如下“扭曲”的地址 最后,python中编译(setup.py文件中extension指定)的c程序,就会出现找不到库的问题。 于是乎,报告这个bug的同时,建议全部用斜杠/。 回复: You need to use raw strings to avoid this. Replace "C:\Program Files (x86)\Graphviz2.38\lib\release\lib" with r"C:\Program Files (x86)\Graphviz2.38\lib\release\lib" See https://blog.lerner.co.il/avoiding-windows-backslash-problems-with-pythons-raw-strings/ for more details about raw strings. This tracker is for issues with bugs.python.org. Please use Stack Overflow or python-list to ask usage questions. 老外不承认是bug。说,windows反斜杠的处理,要加r。嗯嗯。就这样吧。 解决方案见网址: https://github.com/pygraphviz/pygraphviz/issues/58 仍然是下面的这个网址: https://github.com/pygraphviz/pygraphviz/issues/58 里面提到:(在网络海量信息中去伪存真) 最后在如下这个网址: https://github.com/pygraphviz/pygraphviz/issues/74#issuecomment-238323405 中找到: 点击进去(https://github.com/Kagami/pygraphviz/commit/fe442dc16accb629c3feaf157af75f67ccabbd6e) 就是一个补丁文件: 按照补丁文件对graphviz.i和pygraphviz/graphviz_wrap.c进行修改(我一行一行对着补丁改的。。。应该有依据补丁的自动化修改工具)。修改后的文件见附件。 上面是测试程序。通过搜集资料可知,是因为neato的问题。双击C:\Program Files (x86)\Graphviz2.38\bin下的neato,会报出异常。 如何解决,见文末总结。 链接:https://pan.baidu.com/s/18VKkVj_CupmvFwihdHwH8Q 密码:aqr7 2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案) 标签:需要 value options OLE rom svc 并且 har compiler 原文地址:https://www.cnblogs.com/xiaojieshisilang/p/9495295.html已有博文存在的问题:windows下pygraphviz?1.3.1?cp34?none?win_amd64.whl文件无法适用于python3.6版本
pip install pygraphviz?1.3.1?cp27?none?win_amd64.whl
基于pygraphviz源码包的方式安装
第一个问题:缺失vc14
第二个问题:缺失头文件
error: command ‘C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\cl.exe‘ failed with exit status 2第三个问题:cannot open input file ‘cdt.lib‘
即链接所有库,生成可执行程序的时候,却提示无法打开cdt.lib文件,我们看到这里面的寻址路径中并没有之前修改setup.py文件中添加的那句话:library_dirs=[‘C:\Program Files (x86)\Graphviz2.38\lib\release\lib‘]
debugfile(‘H:/pygraphviz-master-wrong2/setup.py‘, args=‘install‘, wdir=‘H:/pygraphviz-master-wrong2‘)
[‘C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib‘]为什么在某个环节C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib
变成了C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib
def build_extensions(self):
# First, sanity-check the ‘extensions‘ list
self.check_extensions_list(self.extensions)
for ext in self.extensions:
ext.sources = self.cython_sources(ext.sources, ext)
self.build_extension(ext)
ipdb> print (ext.library_dirs)
[‘C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib‘]
self.extensions = self.distribution.ext_modules
log.info("running %s", command)
cmd_obj = self.get_command_obj(command)
cmd_obj.ensure_finalized()
cmd_obj.run()
"""Return the command object for ‘command‘. Normally this object
is cached on a previous call to ‘get_command_obj()‘; if no command
object for ‘command‘ is in the cache, then we either create and
return it (if ‘create‘ is true) or return None.
"""
cmd_obj = self.command_obj.get(command)
self.extensions = self.distribution.ext_modules
呕血调试发现python的bug
library_dirs=[‘C:\Program Files (x86)\Graphviz2.38\lib\release\lib‘],
C:\\Program Files (x86)\\Graphviz2.38\\lib\release\\lib
提交了bug,和处理结果(被老外狠狠的鄙视了一把,他不认为是bug)
msg3530 (view) Author: berker.peksag Date: 2018-08-20.16:26:32
remove
> In windows, we always give a path using ‘\‘ and python 3 can correctly dispose
> it just as we using ‘/‘ in Linux. But if you offer
> a path in windows with a ‘\‘ followed as ‘r‘. Everyting will goes wrong.第四个问题:unresolved external symbol agwrite
这里面说用64位lib下的库文件覆盖到目录lib下即可。也就是说这些unresolved是缺失了一些库。可以看到是生成_graphviz.cp36_win_amd64.lib的时候出错。这是因为安装的graphviz是32位的模块,缺失了很多库文件。
这个库,会放在本文附件里。
接着问题就能排除。
注意是将我附件中的\GraphViz_x64-master\graphviz-2.38_x64\lib放置到:
graphviz的msi安装程序之后的release的lib下面,而不是直接的lib下面C:\Program Files (x86)\Graphviz2.38\lib\release\lib。
但是,仅仅覆盖lib文件时不够的。否则在后续的测试程序中,import pygraphviz的时候回报错提示,dll win32位的有问题。
所以,除了lib路径需要特殊处理以外,需要把附件中GraphViz_x64-master\graphviz-2.38_x64中的
所有的内容全部覆盖到C:\Program Files (x86)\Graphviz2.38中去。(所以,你直接换个名字吧。具体见文末的总结) 倒数第二个问题:unresolved external symbol PyIOBase_Type
最后一个问题,测试程序时输出ValueError: Program neato not found in path。
import pygraphviz as pgv
A=pgv.AGraph()
A.add_edge(1,2)
A.add_edge(2,3)
A.add_edge(1,3)
print(A.string()) # print to screen
print("Wrote simple.dot")
A.write(‘simple.dot‘) # write to simple.dot
B=pgv.AGraph(‘simple.dot‘) # create a new graph from file
B.layout() # layout with default (neato)
B.draw(‘simple.png‘) # draw png
print("Wrote simple.png")
附件
总结,全部安装过程
文章标题:2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案)
文章链接:http://soscw.com/index.php/essay/105452.html