☰
networkx 1.11.zip安装:Python版本兼容与排错
2026/10/30 3:17:00 网站建设 项目流程

简介:networkx-1.11.zip 是面向 Python 开发者、复杂网络研究者与图论学习者的经典网络分析库源码包,适用于社交网络建模、路径与连通性分析、图算法教学及旧项目维护等场景。包内共收录 594 个文件,其中 429 个 .py 源码构成核心模块,117 个 .rst 文档与若干 txt 说明提供 API 与使用指引,另有 bz2、gz、gpickle 等压缩样例数据和 png、html、css 等辅助文件,压缩包约 1.47MB,体量轻便、目录层次清晰。已有 83 人学习下载。读者可据此研读图结构、节点与边属性、最短路、中心性、连通分量等算法的实现方式,结合随包文档与样例数据完成环境验证、源码比对和二次开发;文档与测试材料也有助于理解接口设计、定位版本差异,并作为课程演示与实验复现的参考。压缩包内保留原始发布结构,便于按模块检索与对照不同版本的实现差异。

1. networkx-1.11.zip 安装:先对 Python 版本,再谈解压

前阵子帮人复现一份老图算法实验,环境说明只有一行「装 networkx-1.11.zip」。照做,在 3.11 的解释器上pip install一路绿灯,敲下import networkx却直接抛出AttributeError: module 'collections' has no attribute 'Iterable'。包本身没坏,坏的是版本对位:networkx 1.11 是纯 Python 的图论库,官方只认 Python 2.7 和 3.3~3.5 这几代解释器,扔到 3.10 以后必然翻车。这类 zip 源码包在内网离线机器、老论文复现、旧项目维护里特别常见,装不好不会报「装错了」,而是静默加载到系统里躺着的旧版本,或者绘图模块悄悄缺失,跑到一半才发现结果不对。下面按装前盘点、三条安装路径、环境配置、踩坑排查、最终验证的顺序走一遍。

2. 装前环境盘点:Python 2.7/3.5 与 setuptools、可选依赖的版本矩阵

动手之前先做两件事:确认解释器大版本,确认有没有历史版本抢占路径。networkx 1.11 没有 C 扩展,也没有硬性运行时依赖,setup.py里几乎不写install_requires,这意味着它对环境很宽容,也意味着装错了不会有任何提示——pip 不会告诉你「这个版本在你的解释器上跑不起来」,它只会把文件铺进 site-packages,等你自己在 import 时撞墙。所以盘点这一步不是形式主义,是把后面所有玄学问题提前掐掉。

2.1 解释器对照:1.11 能落在哪些 Python 上

先把当前解释器版本打出来,别信python这个别名指向谁:

# 先看清 python 到底是谁,很多机器上 python 指向 2.7,python3 才是 3.x python -V python -c "import sys; print(sys.version_info[:2])" which -a python python3 # 列出所有同名解释器,确认优先级

which -a这一步值得养成习惯:一台跑过几年项目的机器上,/usr/bin/python、/usr/local/bin/python3、某个 conda 环境里的 python 可能同时存在,PATH 顺序决定了你装到了哪一份里。

对照关系大致是这样:

解释器版本networkx 1.11 的实际表现我一般怎么处理
Python 2.7官方支持,最稳老项目直接上,不用犹豫
Python 3.3 / 3.4 / 3.5官方支持新环境优先选 3.5,生态最全
Python 3.6 / 3.7核心图算法正常,个别模块抛 DeprecationWarning启动加-W ignore::DeprecationWarning
Python 3.8 / 3.9collections 别名开始告警,部分模块 import 即报错别在生产上赌,换 3.5 或升 2.x
Python 3.10 及以上别名移除,import 阶段直接 AttributeError降解释器,或按第 5 章打补丁

这张表不是吓唬人。1.11 这个版本的代码写于 Python 3.3 时代,里面大量沿用了collections.Iterable、collections.Mapping这类写法,而这些别名在 3.3 被标记弃用、3.10 被彻底删除。新版解释器不会给你兼容层,只会给你一个看起来莫名其妙的 AttributeError。

2.2 可选依赖:matplotlib、numpy、PyYAML、pydot 各管一段路

networkx 1.11 本体只依赖标准库,但它的很多常用能力被拆到了可选依赖里。这些包不装也能 import networkx,只是调用到具体函数时才报错,属于典型的「装的时候没问题、用的时候才发现缺」:

可选依赖不装的后果装上后解锁
matplotlibnx.draw系列直接 ImportError画图、布局预览、导出 PNG
numpy邻接矩阵相关计算退化到纯 Python,慢一个量级adjacency_matrix返回 ndarray
scipy稀疏矩阵相关函数不可用大规模稀疏图运算
PyYAMLread_yaml/write_yaml报错YAML 格式读写
pydot + Graphvizread_dot/write_dot不可用DOT 文件互转
nosenx.test()跑不起来全量单元测试

我一般的取舍是:只做图算法计算,一个可选依赖都不装,装完就能用;要做可视化,matplotlib 必装;要跑全量单测做验收,再补 nose。注意 nose 本身在 3.10 以后已经跑不动了,如果你把解释器降到 3.5 就没这个问题,这也是我把 3.5 排在首选的原因之一。

# 只补可视化所需,numpy 交给 matplotlib 顺带拉进来 python -m pip install "matplotlib<3.0"

matplotlib<3.0这个上限不是随手写的:1.11 时代的绘图接口跟新版 matplotlib 之间有过若干次签名变动,把上限压住能省掉一堆TypeError: draw_networkx_nodes() got an unexpected keyword argument之类的报错。具体压到哪个版本看你的解释器,3.5 环境下 2.x 系列通常就够。

2.3 解压后先看目录:认准 setup.py 所在的真正根目录

zip 源码包最容易被忽略的一步是确认根目录。Windows 资源管理器解压时,如果压缩包内部本来就有顶层文件夹,很容易解出networkx-1.11/networkx-1.11/setup.py这种双层结构,然后在错误的层级执行安装命令,报error: package directory 'networkx' does not exist。

先不解压,直接看顶层结构:

# 只看压缩包前 20 行清单,确认根目录名和 setup.py 的位置 unzip -l networkx-1.11.zip | head -n 20

正常应该能看到setup.py、setup.cfg、MANIFEST.in、README.txt、INSTALL.txt、LICENSE.txt这几个文件,以及一个networkx/包目录和doc/、examples/之类的辅助目录。判断标准只有一条:setup.py必须和networkx/目录同级。同级就说明这是源码根目录,可以在这里执行安装;不同级就往上找一层。

解压路径也别踩坑:

# 指定纯英文、无空格的短路径,避免 setup.py 解析相对路径时出错 mkdir -p ~/src && unzip networkx-1.11.zip -d ~/src/ ls ~/src/networkx-1.11/setup.py

带中文或者带空格的目录,在老版本 setuptools 上偶发路径解析异常,虽然不是每次必现,但排查成本极高。既然只需要换一个目录名,就没必要省这一步。

3. 安装落地:pip 吃 zip、setup.py 与 PYTHONPATH 直挂三条路

三条路径各有适用场景,不是谁比谁高级。想省事、想留卸载记录,走 pip 吃 zip;环境老、pip 版本低甚至没有 pip,走 setup.py;只想临时试一下、不想污染任何环境,走 PYTHONPATH 直挂。三条路我都装过,下面把命令和判断依据写清楚。

3.1 路径一:pip 直接安装 zip 包

pip 从 1.4 之后就能直接处理本地 zip 源码包,不需要先手工解压:

# --no-deps 跳过依赖解析,1.11 没有硬依赖,离线机器上这一步很关键 # --no-index 完全不访问索引,纯本地安装,内网环境必需 python -m pip install --no-deps --no-index ./networkx-1.11.zip

三个参数各自的作用:--no-deps让 pip 不要顺着install_requires去联网抓依赖,1.11 的依赖列表基本是空的,加上它纯粹是为了断网环境下不卡住;--no-index关掉索引查询,配合本地文件路径就能完成一次完全离线的安装;写成python -m pip而不是直接pip,是为了保证用的是当前解释器自带的那份 pip,多版本共存时这一步能省掉大量「我明明装了怎么找不到」的困惑。

如果目标不是全局环境,而是想把库塞进项目目录随身带:

# 装到项目内的 vendor 目录,随代码一起提交,适合交付给别人的离线包 python -m pip install --no-deps --target=./vendor ./networkx-1.11.zip

--target的代价是运行时得自己把./vendor加进sys.path,好处是整个依赖可以跟代码一起打包拷走,对方机器上不需要任何安装动作。做离线交付时我一直用这个方式。

3.2 路径二:解压 + setup.py install,留一份后悔药

老环境里最稳的还是 setup.py,尤其是 pip 版本太低、或者 pip 因为各种原因装不动的时候:

cd ~/src/networkx-1.11 # --record 把本次安装写下的每个文件路径记到 files.txt python setup.py install --record files.txt

--record这个参数值得单独说。setup.py install不产生卸载入口,装错了想清理只能靠回忆,而files.txt就是那颗后悔药:

# 反向卸载:按记录逐行删除,再清掉空的包目录 cat files.txt | xargs rm -rf

注意xargs rm -rf会删掉文件里记录的每一行路径,执行前先cat看一眼,确认没有把系统路径带进去。这是我在测试机上唯一敢用的暴力卸载方式,生产环境还是老老实实用虚拟环境隔离。

如果当前用户对全局 site-packages 没有写权限,直接 install 会报error: can't create or remove files in install directory。两个选择:

# 选择一:装到用户目录,不需要 sudo python setup.py install --user # 选择二:装到自定义前缀,之后靠 PYTHONPATH 找到它 python setup.py install --prefix=$HOME/.local/nx111

--user之后包会落到~/.local/lib/pythonX.Y/site-packages,这个路径默认就在sys.path里,装完直接能 import。--prefix则完全脱离默认搜索路径,必须配合下一章的环境变量配置,灵活但多一步。

3.3 路径三:免安装,PYTHONPATH 直挂源码目录

只想临时验证某个函数行为,或者同时对比 1.11 和 2.x 的差异,最省事的是根本不装:

# 把源码根目录(含 networkx/ 的那一层)挂到 PYTHONPATH 最前面 export PYTHONPATH=$HOME/src/networkx-1.11:$PYTHONPATH python -c "import networkx; print(networkx.__version__, networkx.__file__)"

这里有一个高频错误:PYTHONPATH 要指向包含networkx/目录的那一层,不是指向networkx/本身。指错了会得到ModuleNotFoundError: No module named 'networkx',然后开始怀疑人生。判断方法很简单,ls $PYTHONPATH应该能看到networkx这个子目录名。

这种方式的另一个好处是切换成本为零:改一行export,重启终端就是一个全新的版本环境,不需要卸载、不需要清缓存。

3.4 装完确认落点:__file__、pth 与多版本共存

不管你走哪条路,装完第一件事都是确认装到哪去了:

# 三行确认:版本号、物理路径、子模块能否正常导入 python -c " import networkx as nx print(nx.__version__) # 期望 1.11 print(nx.__file__) # 期望在你刚装的那条路径下 from networkx.algorithms import shortest_paths # 粗查包体完整性 "

如果__file__指向的路径跟你预想的不一致,多半是系统里本来就有一份旧版本,而且它的路径排在你的前面。setup.py install在某些 setuptools 版本下会生成 egg 目录并往easy-install.pth里写一行路径,这一行和 pip 安装的目标目录可能不是同一个,两台机器上表现出的「同一个命令装出两个结果」,源头基本都在这里。

# 找出所有 pth 文件里的 networkx 相关行,定位路径冲突 grep -r "networkx" $(python -c "import site; print(site.getsitepackages()[0])")/*.pth 2>/dev/null

多版本共存时,我习惯给每个虚拟环境起一个带版本号的名字,比如nx111、nx241,激活后看提示符就知道自己在哪个环境里,比反复print(nx.__file__)省心。

4. 环境配置:虚拟环境隔离、绘图后端与路径这三处最容易配错

装完能 import 只是及格线,真正让人卡住的是配置:环境之间互相污染、绘图在服务器上画不出来、路径顺序不对导致加载了别的版本。这三处配好,后面基本不会再出问题。

4.1 用 virtualenv 建两套沙箱:2.7 与 3.5 各一份

如果你的项目里同时有 Python 2.7 才能跑的老脚本和 3.5 的新代码,别在主环境里折腾,直接建两个沙箱:

# 3.5 环境,用来跑 1.11 的主要计算 virtualenv -p /usr/bin/python3.5 ~/envs/nx111 source ~/envs/nx111/bin/activate python -V # 2.7 环境,用来兼容更老的脚本 virtualenv -p /usr/bin/python2.7 ~/envs/nx111py2 source ~/envs/nx111py2/bin/activate

Windows 上的激活命令是~/envs/nx111/Scripts/activate,路径分隔符不同,其余逻辑一致。虚拟机或容器里如果没有python3.5这个可执行文件,virtualenv -p会直接失败并提示找不到解释器,这时候要么装对应版本,要么退回 PYTHONPATH 方案。

沙箱建好之后,所有安装都在激活状态下做。这样卸载只需要删目录,不需要--record,也不会有任何残留。

4.2 matplotlib 后端与nx.draw的落地配置

服务器上没有显示器,nx.draw默认走交互式后端,很容易卡住或者报no display name and no $DISPLAY environment variable。解决办法是在导入 pyplot 之前把后端切成 Agg:

# 后端必须在 import pyplot 之前设置,顺序反了不生效 import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import networkx as nx # 让中文标签正常显示,字体名要填系统里真实存在的 plt.rcParams["font.sans-serif"] = ["DejaVu Sans"] plt.rcParams["axes.unicode_minus"] = False G = nx.complete_graph(5) nx.draw(G, with_labels=True, node_color="#9ecae1") plt.savefig("graph.png", dpi=120)

matplotlib.use("Agg")是纯文件输出后端,不依赖任何图形界面,CI 环境和服务器上必选。font.sans-serif那一行,列表里填的是系统已安装字体名,填一个不存在的名字 matplotlib 会一路报警告最后画出一堆方框,所以别抄别人的配置,先fc-list看一眼自己机器上有什么。axes.unicode_minus = False是为了让负号正常渲染,跟中文无关但经常一起配。

如果只用 networkx 做计算、不做图,这一段可以整段跳过,少装一个 matplotlib 能省掉很多版本对齐的麻烦。

4.3 PYTHONPATH 与sys.path的顺序陷阱

Python 的模块查找是「先命中先用」,sys.path里靠前的路径优先。用--prefix或者--target装的包,如果不显式把路径插到最前面,就会被 site-packages 里的旧版本截胡:

import sys # insert(0) 而不是 append,必须排在任何 site-packages 之前 sys.path.insert(0, "/home/user/.local/nx111/lib/python3.5/site-packages") import networkx as nx print(nx.__version__) # 这时候才是你指定那一份 print(nx.__file__)

这段代码适合放在项目的启动入口或者conftest.py里,一次性解决。用append的话,路径排在末尾,只要系统里装过任何一个 networkx,加载到的都不是你想要的版本,而且不会报错——这是最难查的一类问题,因为它表现得像「算法结果不对」而不是「导入失败」。

环境变量版本同理,export PYTHONPATH=/your/path:$PYTHONPATH里的$PYTHONPATH不能省,省了就把别人设好的路径覆盖掉了。

5. 避坑与排查:五条把 networkx 1.11 装进项目时的真实翻车记录

下面这几条都是我在不同机器上真实撞过的,按「现象 → 原因 → 解决」整理,遇到对应症状可以直接对号入座。

第一条:import 成功,但版本号不对。

现象:import networkx不报错,nx.__version__打出来是 1.8.1 或者 1.9.1,跟你装的 1.11 完全不是一回事;算法结果和文档对不上,某些函数还提示不存在。

原因:系统 site-packages 里本来就躺着一份旧版本,而且它在sys.path里的位置排在前面。setup.py install往另一个 site-packages 写入了新版本,但 Python 只认先命中的那个。装了不等于生效,这是最典型的静默失败。

解决:先用python -c "import networkx; print(networkx.__file__)"定位实际加载路径,确认跟你预期的安装目录是否一致。不一致就先pip uninstall networkx清掉旧版本,再重装;不方便卸载的,用第 4.3 节的sys.path.insert(0, ...)强行提权。最彻底的办法还是虚拟环境,物理隔离比路径操作可靠得多。

第二条:权限错误,装到一半中断。

现象:python setup.py install执行到一半报error: can't create or remove files in install directory,或者Permission denied,前面几条copying ...已经刷过去了,环境处于半装状态。

原因:当前用户对全局 site-packages 没有写权限。多人共用的机器上这是常态,很多人习惯性加sudo,结果把包装进了 root 的路径里,自己反而 import 不到。

解决:优先用--user装到用户目录,或者直接进虚拟环境。已经半装坏的,按files.txt里记录的路径反删干净再重来;没有 record 的,就pip uninstall networkx试一次,不行就手工进 site-packages 删掉networkx目录和networkx-1.11*.egg-info。

第三条:setup.py找不到包目录。

现象:执行python setup.py install报error: package directory 'networkx' does not exist,但你明明看到networkx文件夹就在旁边。

原因:两层目录。压缩包内部本来有一个顶层文件夹,解压工具又套了一层,实际结构变成networkx-1.11/networkx-1.11/setup.py,你在外层执行,setup.py 相对路径就找不到同级包目录。另一种情况是解压到了带中文或空格的路径,老版本 setuptools 解析时出错。

解决:ls确认setup.py与networkx/同级后再执行;不确定就先pwd打一下当前目录。路径问题一律换成~/src/这种纯英文短路径,成本最低。

第四条:3.8 以上解释器 import 就炸。

现象:AttributeError: module 'collections' has no attribute 'Iterable',或者满屏DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc'。

原因:1.11 里不少模块沿用了collections.Iterable、collections.Mapping这类 3.3 时代的写法,这些别名从 3.3 起被标记弃用,3.10 起被彻底移除。新版解释器不给兼容层,直接抛异常。

解决:最干净的是把解释器降到 3.5。实在降不了,在 import networkx 之前打一个补丁:

# py310_patch.py:把被移除的别名从 collections.abc 补回 collections import collections import collections.abc for _name in ("Iterable", "Mapping", "MutableMapping", "Sequence", "Callable"): if not hasattr(collections, _name): setattr(collections, _name, getattr(collections.abc, _name)) import networkx as nx # 补丁必须在这行之前生效 print(nx.__version__)

补丁要放在项目入口最前面,或者写成sitecustomize.py让解释器启动时自动加载。hasattr判断不能省,否则在老解释器上会把已经存在的属性覆盖掉。

第五条:读写文件后节点标签全变成字符串。

现象:G = nx.karate_club_graph()之后nx.write_gml(G, "k.gml"),再H = nx.read_gml("k.gml"),G.nodes() == H.nodes()返回 False,节点从整数变成了'0'、'1'这样的字符串。

原因:1.x 的read_gml把 label 一律按字符串解析,没有后来的 destringizer 参数。这不是 bug,是那个版本的既定行为。

解决:读回来之后手工转一次,或者换格式:

import networkx as nx H = nx.read_gml("k.gml") H = nx.relabel_nodes(H, {n: int(n) for n in H.nodes()}) # 按原类型批量回转

转的时候注意原图节点类型,字符串键混数字键的图别硬转,容易撞键。跨版本交换数据我更倾向 edgelist 或 pickle,注意 pickle 在不同 Python 大版本之间不保证兼容,只在同版本环境内部流转时用。

6. 装完怎么验证:三个最小用例确认图算法真的跑通

版本号对、__file__对,只能说明文件放对了位置,不能说明这套环境能干活。我的验收动作固定是三个用例,覆盖建模、算法、读写三段链路,加起来不到一分钟。

第一段,建图和最短路,验证核心数据结构与算法层:

import networkx as nx G = nx.Graph() G.add_weighted_edges_from([ ("A", "B", 2.0), ("B", "C", 3.0), ("A", "C", 10.0), ("C", "D", 1.0), ]) print(nx.shortest_path(G, "A", "D", weight="weight")) # ['A', 'B', 'C', 'D'] print(nx.shortest_path_length(G, "A", "D", weight="weight")) # 6.0 print(dict(nx.degree(G))) # 各节点度数

期望的路径是A→B→C→D,总权重 6.0。如果没传weight="weight",会退化成按跳数算,结果变成A→C→D,看起来也能跑但值不对,很多人以为是自己算法写错,其实是参数漏了。

第二段,跑一个纯 Python 实现的中心性算法,验证较复杂的模块也能正常加载:

# 介数中心性在 1.x 里是纯 Python 实现,能跑通说明算法模块完整 print(nx.betweenness_centrality(G)) print(nx.clustering(G))

第三段,走一遍读写,验证 I/O 层和文件编码没出问题。用 edgelist 最稳,不会踩到 GML 的字符串标签坑:

nx.write_edgelist(G, "g.edgelist", data=True) H = nx.read_edgelist("g.edgelist", data=True) print(H.number_of_nodes(), H.number_of_edges()) # 应与原图一致

三段跑完,再补一句全量单测(装了 nose 才有):

python -c "import networkx; networkx.test()"

单测跑不全没关系,Ran X tests那一行能出来就说明包体完整;报ModuleNotFoundError: No module named 'nose'就是可选依赖没装,不算安装失败。

验证项通过标准不通过的典型原因
版本与路径__version__为 1.11,路径指向安装目录旧版本抢占 sys.path
建图与最短路路径['A','B','C','D'],长度 6.0漏传weight参数
读写往返节点数与边数与原图一致GML 标签类型变化,换 edgelist
单测能输出Ran N tests未装 nose,或解释器版本过高

从那以后我每次装这种老版本纯 Python 包,都强制先把__version__和__file__两行打出来,再跑一遍最短路和读写往返,确认无误才往项目里引。这三步花不了一分钟,省下的却是半天翻日志的时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询