首页 > Python资料 博客日记
使用mirror.ghproxy.com加速raw.githubusercontent.com以解决brew upgrade python@3.12慢的问题
2024-10-15 05:00:07Python资料围观67次
本篇文章分享使用mirror.ghproxy.com加速raw.githubusercontent.com以解决brew upgrade python@3.12慢的问题,对你有帮助的话记得收藏一下,看Python资料网收获更多编程知识
MacOS系统上,升级python3.12时,超级慢,而且最后还失败了。看了日志,发现是用curl从raw.githubusercontent.com上下载Python安装包超时了。
解决方案一:开启VPN工具,穿越围墙
解决方案二:使用mirror.ghproxy.com加速raw.githubusercontent.com
穿墙有风险,操作需谨慎,这里我采用的是方案二。
1. 查看curl路径
which curl
# /usr/bin/curl
2. 编写自定义脚本,并赋予执行权限
ln -s `which curl` /usr/local/bin/curl
[ -d ~/.local/bin ] || mkdir -p ~/.local/bin/
cd ~/.local/bin
touch curl
chmod +x curl
# 注:PATH要配置到.bashrc或.zshrc里,别的窗口才能起作用
export PATH=$HOME/.local/bin:$PATH
vi curl
which curl
# ~/.local/bin/curl
3. 脚本内容
#!/usr/bin/env python
import os
import re
import sys
try:
from typing import List # NOQA:F401
except ImportError:
pass
RE_SKIP = re.compile(r'\.(zip|rar|7z|apk|ipa|exe|msi|m3u|m3u8|mp4|mp3)$')
def rewrite_url(i, scheme):
# type: (str, str) -> str
proxy = "mirror.ghproxy.com"
domains = ("raw.githubusercontent.com", "gist.githubusercontent.com")
# TODO: use personal Cloudflare Worker instead.
j = i[len(scheme) :]
for domain in domains:
if j.startswith(domain):
if not RE_SKIP.search(j):
i = scheme + proxy + '/' + i
break
return i
def gen_cmd(sys_argv):
# type: (List[str]) -> str
args = []
scheme = "https://"
for i in sys_argv[1:]:
if i.startswith(scheme):
i = rewrite_url(i, scheme)
elif " " in i:
i = repr(i)
args.append(i)
tool = "/usr/local/bin/" + sys_argv[0].split("/")[-1]
cmd = tool + " " + " ".join(args)
return cmd
def main():
# type: () -> int
sys_argv = sys.argv
if "--dry" in sys_argv:
sys_argv = [i for i in sys_argv if i != "--dry"]
print("-->", gen_cmd(sys_argv))
return 0
return os.system(gen_cmd(sys_argv))
if __name__ == "__main__":
sys.exit(main())
4. 测试效果
curl https://raw.githubusercontent.com/Homebrew/homebrew-core/a775cbd0967da13128293d71fb26431fdedee6fb/Formula/m/mpdecimal.rb
5. 重新执行升级命令(这时候就很快了,不到一分钟就下载完毕,十分钟内就完成升级)
brew upgrade python@3.12
注: wget也可以用类似的方法加速
################# 2024.02.08 补充:
如果有外网服务器,还可以配个中转请求:
1. 本地curl文件内容如下(需export JUMPER_IP='<服务器IP地址>')
#!/usr/bin/env python
import os
import sys
try:
from typing import List # NOQA:F401
except ImportError:
pass
def gen_cmd(sys_argv):
# type: (List[str]) -> str
args = []
scheme = "https://"
origin, target = "raw.githubusercontent.com", "raw.gitmirror.com"
domains = ("objects.githubusercontent.com", "github.com")
redirect = os.getenv("JUMPER_IP")
host = "http://{}:9337/".format(redirect)
for i in sys_argv[1:]:
if i.startswith(scheme):
j = i[len(scheme) :]
if j.startswith(origin):
i = i.replace(origin, target)
elif redirect:
for domain in domains:
if j.startswith(domain):
i = host + j
break
elif " " in i:
i = repr(i)
args.append(i)
tool = "/usr/local/bin/" + sys_argv[0].split("/")[-1]
cmd = tool + " " + " ".join(args)
return cmd
def main():
# type: () -> int
sys_argv = sys.argv
if "--dry" in sys_argv:
sys_argv = [i for i in sys_argv if i != "--dry"]
print("--> " + gen_cmd(sys_argv))
return 0
return os.system(gen_cmd(sys_argv))
if __name__ == "__main__":
sys.exit(main())
2. 服务器上的app.py文件如下:
#!/usr/bin/env python
import re
# pip install httpx orjson loguru sanic gunicorn 'uvicorn[standard]'
from httpx import AsyncClient
from loguru import logger
from orjson import dumps, loads
from sanic import Sanic, raw
app = Sanic("Jumper", dumps=dumps, loads=loads)
@app.route("", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
async def index(request):
return raw(b"Welcome. Example>> http :8000/http.127.0.0.1:9000/home")
@app.route("/<full:path>", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
async def handler(request, full: str):
host, url = full.lstrip("/"), ""
if m := re.search(r"(https?)[^0-9a-zA-Z]+(.+)", host):
scheme, host = m.groups()
else:
scheme = "https"
try:
domain, url = host.split("/", 1)
except ValueError:
domain = host
base_url = scheme + "://" + domain
target_path = url
if qs := request.query_string:
target_path += "?" + qs
if not target_path:
target_path = base_url
if not target_path.startswith("/") and not target_path.startswith("http"):
target_path = "/" + target_path
logger.debug(f"{base_url=}; {target_path=}")
async with AsyncClient(
base_url=base_url, follow_redirects=True, timeout=20
) as client:
method, body = request.method, request.body
r = await client.request(method, target_path, content=body)
if r.status_code == 302 and (next_url := r.headers.get("location")):
r = await client.request(method, next_url, content=body)
return raw(r.content, status=r.status_code)
if __name__ == "__main__": # pragma: no cover
app.run(debug=True, host="0.0.0.0")
3. 后台启动服务:
gunicorn app:app --bind 0.0.0.0:9337 --worker-class uvicorn.workers.UvicornWorker --daemon
4. 本地brew对应的install文件修改如下:
cd $(brew --prefix)/Homebrew/Library/Homebrew
grep -rn Downloading *.rb
# download_strategy.rb:426:
vi download_strategy.rb # 给download的url增加前缀
git diff
增加这几行:
if (domain = Homebrew::EnvConfig.artifact_domain)
url = url.sub(%r{^https?://#{GitHubPackages::URL_DOMAIN}/}o, "#{domain.chomp("/")}/")
+ elsif url.start_with?("https://cdn.")
+ puts "Leave #{url} to be itself."
+ elsif !url.start_with?("https://mirrors.")
+ url = "http://your-server-ip-or-domain/" + url
end
ohai "Downloading #{url}"
即除了mirrors和cdn开头的域名,全都使用自建域名加速
elsif url.start_with?("https://cdn.")
puts "Leave #{url} to be itself."
elsif !url.start_with?("https://mirrors.")
url = "https://your.domain.com/" + url
################################
2024.03.06 补充 (Updated@2024.08.29)
Thanks to https://github.com/hunshcn/gh-proxy
步骤4可以用如下Python脚本来实现:
#!/usr/bin/env python
"""
This script is used to improve download speed for `brew install`
Usage::
$ python pad_brew_download_url.py
"""
import os
import subprocess
HOST = "https://mirror.ghproxy.com/"
PY_HOST = "https://mirrors.huaweicloud.com/python/"
PAD = """
elsif (url.start_with?("https://cdn.") || url.start_with?("https://desktop.docker.com"))
puts "Leave #{url} to be itself."
elsif (url.start_with?("https://ftpmirror.") || url.start_with?("https://ftp.gnu.org"))
puts "Skip #{url} padding."
elsif url.start_with?("https://www.python.org/ftp/python/3.")
url = "%s" + url[34,url.length]
elsif !url.start_with?("https://mirror")
url = "%s" + url
"""
def say_done():
# type: () -> None
try:
from rich.console import Console
except ImportError:
print("\nDone~\n")
else:
console = Console()
console.log("[bold magenta]Done.[/bold magenta]", ":vampire:")
def capture_output(cmd):
# type: (str) -> str
try:
r = subprocess.run(cmd, shell=True, capture_output=True)
except (TypeError, AttributeError): # For python<=3.6
with os.popen(cmd) as p:
return p.read().strip()
else:
return r.stdout.decode().strip()
def remove_old_pad(text, s):
# type: (str, str) -> str
s_index = text.index(s)
pre = text[:s_index]
lines = pre.splitlines()
length = len(lines)
if_index = length
for i in range(length - 1, -1, -1):
line = lines[i]
if line.strip().startswith("if "):
if_index = i
break
elif_index = 0
start = if_index + 2
for i, one in enumerate(lines[start:], start):
if one.strip().startswith("elsif "):
elif_index = i
break
if elif_index:
cut = "\n".join(lines[:elif_index])
if pre.endswith("\n"):
cut += "\n"
text = cut + text[s_index:]
return text
def main():
# type: () -> None
brew_root = capture_output("brew --prefix")
folder = "Homebrew/Library/Homebrew"
name = "download_strategy.rb"
file = os.path.join(brew_root, folder, name)
with open(file) as f:
text = f.read()
pad = (PAD % (PY_HOST, HOST)).lstrip("\n")
if pad in text:
print("{} already in {}\nNothing to do!".format(HOST, file))
return
bak_file = file + ".bak"
if not os.path.exists(bak_file):
with open(bak_file, "w") as fp:
fp.write(text)
print("Create backup file at: {}".format(bak_file))
s = ' end\n\n ohai "Downloading #{url}"'
text = remove_old_pad(text, s)
new_text = text.replace(s, pad + s)
with open(file, "w") as f:
f.write(new_text)
print("Insert\n{} into {}".format(pad, file))
say_done()
if __name__ == "__main__":
main()
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj