前言:
许多公司,出于数据安全与知识产权的原因,在公司内部搭建局域网进行算法开发。配置一个本地的pypi镜像源对工程开发十分重要。搭建本地pypi镜像源的工具有多种,本文主要介绍pip2pi方法。
第一步:新建项目,创建环境,安装项目依赖包
项目依赖包列表mirror-project-env-requirements.txt为:
beautifulsoup4==4.11.1
bs4==0.0.1
certifi
charset-normalizer==2.1.1
idna==3.4
lxml==4.9.1
numpy==1.21.6
pandas==1.3.5
pip2pi==0.8.2
python-dateutil==2.8.2
pytz==2022.6
requests==2.28.1
six==1.16.0
soupsieve==2.3.2.post1
urllib3==1.26.13
wincertstore==0.2
创建环境,在线安装依赖包
# 创建环境
conda create -n build_pypi_mirror_env python=3.7
# 激活环境
conda activate build_pypi_mirror_env
# 安装依赖包
pip install -r mirror-project-env-requirements.txt
第二步:下载pypi包到本地
为了快速体验,本文下载当前项目环境中的依赖包。
# 创建文件夹
mkdir D:/PypiPackages
# 把pypi包下载到文件夹
pip download -d D:/PypiPackages -r requirements.txt
第三步:生成pypi包的html索引
dir2pi D:/PypiPackages
如果在win10系统中运行,过程中会报出下面错误,忽略即可,不影响后续过程。
(pypi-build-env) C:\Users\wzg16>dir2pi D:\PypiPackages
ERROR linking ../../beautifulsoup4-4.11.1-py3-none-any.whl to D:\PypiPackages\simple\beautifulsoup4\beautifulsoup4-4.11.1-py3-none-any.whl (skipping): symbolic link privilege not held
ERROR linking ../../bs4-0.0.1.tar.gz to D:\PypiPackages\simple\bs4\bs4-0.0.1.tar.gz (skipping): symbolic link privilege not held
ERROR linking ../../certifi-2022.12.7-py3-none-any.whl to D:\PypiPackages\simple\certifi\certifi-2022.12.7-py3-none-any.whl (skipping): symbolic link privilege not held
ERROR linking ../../charset_normalizer-2.1.1-py3-none-any.whl to D:\PypiPackages\simple\charset-normalizer\charset_normalizer-2.1.1-py3-none-any.whl (skipping): symbolic link privilege not held
ERROR linking ../../idna-3.4-py3-none-any.whl to D:\PypiPackages\simple\idna\idna-3.4-py3-none-any.whl (skipping): symbolic link privilege not held
执行完毕后,会在D:/PypiPackages文件夹下生成一个simple文件夹,存储着python包的html索引。
simple文件夹的内容如下:
第四步:校正index.html的索引格式。
如果是在win10系统中执行的该项目,pip2pi得到的index.html不能直接使用,需要做以下修改(在linux系统中,应该不需要此步骤,暂时还没试):
修改前:
修改后:
主要的修改内容是:在路径上添加了“../../”。
可以手动修改,也可以写一个pyghon脚本批量执行,下面是我写的批量修改的脚本。
import os
import glob
class Class_Util_Text():
def __init__(self):
pass
def read_text(self,text_path):
"""
读取本地text文件到列表,并返回该列表
"""
assert os.path.exists(text_path)
with open(text_path,"r") as f:
lines=f.readlines() #读行
return lines
def write_text(self,text_path,text_content):
"""
把文字写入文本文件中,会清空文本文件的原有内容
"""
with open(text_path,"w") as f:
f.writelines(text_content)
f.writelines("\n")
def append_text(self,text_path,text_content):
"""
把文字添加到文本文件的末尾,保留原文本文件内容
"""
with open(text_path,"a") as f:
f.writelines(text_content)
f.writelines("\n")
def replace_text(self,text_path,replace_old,replace_new):
"""
替换文本文件中的部分文字,先读文件,替换文字后,再重新写入文件
"""
#read
with open(text_path,"r") as f:
lines=f.readlines()
data=[]
for i in lines:
#根据条件修改
if(replace_old in i):
i=i.replace(replace_old,replace_new) #修改 replace_old 为 replace_new
data.append(i) #记录每一行
#write
with open(text_path,"w") as f:
for i in data:
f.writelines(i)
if __name__ =="__main__":
txt_obj = Class_Util_Text()
dir_path = "D:\PypiPackages\simple"
html_files = glob.glob(dir_path+"/*/index.html")
for html_path in html_files:
txt_obj.replace_text(html_path,replace_old="<a href='",replace_new="<a href='../../" )
# txt_obj.replace_text(html_path,replace_old="<a href='../../",replace_new="<a href='" )
lines = txt_obj.read_text(html_path)
print(html_path)
print(lines)
第五步:安装nginx,修改nginx.conf
nginx的下载地址是:https://nginx.org/download/nginx-1.16.1.zip
找到并打开nginx.conf文件,进行以下修改。
server{
listen 8080;
server_name 127.0.0.1:8080;
access_log logs/pip.log;
location / {
root D:\PypiPackages;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
这个步骤的目的/功能是:把文件夹路径与IP地址(127.0.0.1:8080)进行关联。当在浏览器中输入127.0.0.1:8080时,浏览器会定位到D:\PypiPackages文件夹,并搜寻所有的.html文件,在浏览器中显示.html的内容。
第六步:双击nginx.exe,激活nginx。
此时,文件夹路径与IP地址关联成功,通过访问127.0.0.1:8080/smple可以看到D:\PypiPackages文件夹下的pypi包链接,点击链接即可下载package.
注意事项:如果多次更改配置,多次运行nginx.exe,务必保证现在“任务管理器”中结束正在运行的nginx程序,然后重新执行,否则可能修改配置无效。
第七步:配置pip的channel设置,使用自己搭建的本地镜像库安装python相关软件包
永久性:
pip config set global.index-url http://127.0.0.1:8080/simple/# 配置channel
pip install bs4 # 安装bs4
临时性:
pip install bs4 -i http://127.0.0.1:8080/simple/
注意:配置channel时,要在网址后面带上“/simple/”