今天要在没联网的服务器上安装一个python的处理shapefile的库:pyshp,网上查了一下离线安装python库的资料,就把pyshp的压缩包文件下载并上传到服务器上了,结果在执行
python setup.py install
的时候报错:没有setuptools,然后我就走上了艰辛的安装setuptools的道路_(:зゝ∠)_
1. 懵逼状态
一开始我心想,这不简单嘛,和离线安装一个库有什么差别,于是下载了setuptools-20.6.7.tar.gz上传到服务器上解压之后,执行了同样的
python setup.py install
然后看到报错:没有setuptools模块
,我是懵逼的,当时心里就觉得自己蠢哭了_(:зゝ∠)_
2. 查询解决方案
我上网查了一下如何离线安装setuptools。原来是setuptools的压缩包解压之后会有一个 ez_setup.py,setuptools的安装是通过这个文件来实现的,在ez_setup.py文件执行过程中,会去联网下载setuptools的压缩包并自动进行解压以及后续的安装处理,所以网上提到一种方法是将setuptools的压缩包复制到它解压出来的文件夹里,然后执行ez_setup.py。也就是:
a. 解压setuptools-20.6.7.tar.gz压缩包得到一个文件夹,假设名为setuptools-20.6.7
b. 将压缩包setuptools-20.6.7.tar.gz放到解压得到的setuptools-20.6.7文件夹中
c. 在setuptools-20.6.7文件夹中执行python ez_setup.py即可
我安装上述方法试了一下,但是在最后执行ez_setup.py的时候它还是要联网去下载, 并不知道为什么_(:зゝ∠)_
然后又是网上查资料,查原因_(:зゝ∠)_
后来看到另外的一个方法:修改egg(话说这个东西是干什么用的我一直没太明白,好像是存储了一些安装用的文件和信息)的地址:
203 def main(argv, version=DEFAULT_VERSION):
204 """Install or upgrade setuptools and EasyInstall"""
205 try:
206 import setuptools
207 except ImportError:
208 egg = None
209 try:
210 #egg = download_setuptools(version, delay=0)
211 egg="/usr/local/app/setuptools-0.6c11-py2.7.egg"
212 sys.path.insert(0,egg)
213 from setuptools.command.easy_install import main
214 return main(list(argv)+[egg]) # we're done here
215 finally:
216 if egg and os.path.exists(egg):
217 os.unlink(egg)
然后我打开了ez_setup.py,然而它的main函数是长这个样子的:
def main():
"""Install or upgrade setuptools and EasyInstall."""
options = _parse_args()
archive = download_setuptools(**_download_args(options))
return _install(archive, _build_install_args(options))
我当时的内心:
这和说的不一样啊,这都什么鬼啊!
但是之前看到的替换egg地址的那篇文章给我启发:是不是可以将下载好的压缩包传到文件夹里,免去联网下载的环节,直接安装?
我觉得应该可以,于是我就在文件里找了找下载包的代码:
def download_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=DEFAULT_SAVE_DIR, delay=15,
downloader_factory=get_best_downloader):
"""
Download setuptools from a specified location and return its filename.
`version` should be a valid setuptools version number that is available
as an sdist for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
``downloader_factory`` should be a function taking no arguments and
returning a function for downloading a URL to a target.
"""
version = _resolve_version(version)
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
zip_name = "setuptools-%s.zip" % version
url = download_base + zip_name
saveto = os.path.join(to_dir, zip_name)
if not os.path.exists(saveto): # Avoid repeated downloads
log.warn("Downloading %s", url)
downloader = downloader_factory()
downloader(url, saveto)
return os.path.realpath(saveto)
它长这个样子,可以看出:version应该是分析需要下载的版本,to_dir应该是下载后的存放目录,zip_name应该是压缩包的名字,url应该是压缩包所在的位置,saveto应该是压缩包下载后的路径名。经过修改源码输出得到saveto的值之后(又是一段曲折坎坷的经历_(:зゝ∠)_),发现值就是当前文件夹,但是明明我已经上传了压缩包,为什么还要联网下载?!为什么,你怎么这么执着于联网?
后来又静下来仔细比对了一下路径,才发现问题所在:原来ez_setup.py联网下载的那个压缩包是.zip的文件,而我下载传到路径下的是tar.gz的文件!
是在下输了!现在终于有了解决办法:
1. 现在本机浏览器上输入url即下载得到相应版本的zip文件
2. 将zip压缩包上传到ez_setup.py所在的文件夹下
3. 将ez_setup.py中的函数download setuptools函数中的
version = _resolve_version(version)这一句注释掉,因为在_resolve_version函数中需要联网获取最新版本信息,此处因为是自己下载好的压缩包,所以不需要这个信息
4. 将zip_name改为相应的zip压缩包的名字,此处应该不能将其改为.tar.gz,因为后来是调用的zip库中的函数解压,所以改为tar.gz虽然可以通过下载阶段,但是在安装解压的时候可能会出问题
5. 执行ez_setup.py即可
看见setuptools安装完成的界面真的内心激动万分_(:зゝ∠)_ 不枉我没吃早饭地折腾了一早上