ubuntu14.04下利用pypi-server搭建本地的pip库


应实验室需要,自己动手实现了一个pip本地仓库。其实搭建起来很简单,重点在于对本地不存在包的处理。这里我设置的机制是当本地不存在所请求的包时继续维持连接,同时从阿里的pip镜像源中将该包下载到本地以供用户下载。于是,问题主要在于获取所缺失包的信息。

我的解决方法是:当pypi-server在本地找不到所请求包时跳转到主机的另一端口,在此端口上运行一个监听程序,从HTTP请求中获取所要下载的包,然后从阿里的pip镜像库中将该包下载到本地。

1.下载pypi-server


跳转下载


2.pypi-server的使用


pypi-server [option] packages_path


中间可以跟相关的参数,最后跟上本地存储路径

这里只说明一些我所用到的参数:


-p 指明pypi-server所在的端口

--disable-fallback 禁止在找不到包的时候跳转到pypi官网链接

--fallback-url [url]指明找不到包需要跳转的链接


如:pypi-server -p 8080 --fallback-url http://localhost:9000 ~/pypi-packages

pypi-server运行在主机的8080端口,若找不到所请求的包,则跳转到主机的9000端口,本地存储路径为~/pypi-packages


3.监听程序


前一个版本的在使用过程中遇到问题,即pip用户在找不到包时会不断的发送请求,于是本地仓库中便会有大量重复的包。

解决方法:下载包之前先判断当前目录下是否已经存在,存在则直接跳过.....


#coding:utf-8
import threading
import socket
import re
import os
import urllib
import urllib.request as urllib2
encoding = 'utf-8'
BUFSIZE = 1024


# a read thread, read data from remote
class Reader(threading.Thread):
	def __init__(self, client):
		threading.Thread.__init__(self)
		self.client = client
		self.index_url="http://mirrors.aliyun.com/pypi/simple/"
		self.dir_url="http://mirrors.aliyun.com/pypi/packages/source/"
		self.pkgname=""
		self.pkgdir=[]
		self.pkglist=[]
		self.storepath="~/pypi/"
        
	def run(self):
		while True:
			f=open("listen.log","a+")
			data = self.client.recv(BUFSIZE)
			if(data):
				string = bytes.decode(data, encoding)
				f.writelines(string)
				self.pkgname=re.findall("GET /(.*?)/",string)
				self.pkgname="".join(self.pkgname)
				f.writelines("*******the pkgname: "+self.pkgname+"*******")
				self.getpkgdir()
				pkgdir=self.pkgdir
				for pkg in pkgdir:
					if os.path.exists(self.storepath+pkg[1]):
						print("pkg exists!")
						break
					else:
						self.download(self.dir_url+pkg[0])
			else:
				break
		peername=self.client.getpeername()
		f.writelines("close:"+str(peername))
		f.writelines("\n=============================================\n")
		f.close()


	def getpkgdir(self):


		pkg_url=self.index_url+self.pkgname
		request=urllib2.Request(pkg_url)
		response=urllib2.urlopen(request)
		data=response.read().decode("utf-8")
		self.pkgdir=re.findall('(.*?)',data)
	def download(self,url):
		os.system("wget -P %s %s"%(self.storepath,url))
    
	def readline(self):
		rec = self.inputs.readline()
		if rec:
			string = bytes.decode(rec, encoding)
			if len(string)>2:
				string = string[0:-2]
			else:
				string = ' '
		else:
			string = False
		return string


# a listen thread, listen remote connect
# when a remote machine request to connect, it will create a read thread to handle
class Listener(threading.Thread):
	def __init__(self, port):
		threading.Thread.__init__(self)
		self.port = port
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.sock.bind(("0.0.0.0", port))
		self.sock.listen(0)
	def run(self):
		print("listener started")
		while True:
			client, cltadd = self.sock.accept()
			Reader(client).start()
			cltadd = cltadd
			print("accept a connect")
lst  = Listener(8080)   # create a listen thread
lst.start() # then start


4.pip下载


pip install [packagename] -i http://localhost:8080/simple

利用上述命令则可以从本地pip库中下载所需的包


或者利用下述办法,可直接利用pip install [packagename]命令从本地源下载:




//在主文件夹下新建.pip文件夹
mkdir ~/.pip
 
  

cd ~/.pip
//在文件夹.pip中新建pip.conf文件
vim pip.conf
 
  


//在pip.conf文件中添加以下内容
[global]
index-url = http://localhost:8080/simple






你可能感兴趣的:(Python,Ubuntu)