参考:解决buildozer运行下载依赖包问题“fatal:无法访问‘https://github.com/kivy/python-for-android.git”解决过程

作为🀄️国人实在是太惨了,网络被封锁,使用 buildozer 打包还要面临网络封锁的问题

╰─➤  buildozer -v android debug                                                                                                 1 ↵
# Check configuration tokens
# Ensure build layout
# Create directory /Users/ponponon/Desktop/code/me/ideaboom/.buildozer
# Create directory /Users/ponponon/Desktop/code/me/ideaboom/bin
# Create directory /Users/ponponon/Desktop/code/me/ideaboom/.buildozer/applibs
# Create directory /Users/ponponon/Desktop/code/me/ideaboom/.buildozer/android/platform
# Create directory /Users/ponponon/Desktop/code/me/ideaboom/.buildozer/android/app
# Check configuration tokens
# Preparing build
# Check requirements for android
# Search for Git (git)
#  -> found at /opt/homebrew/Cellar/git/2.49.0/bin/git
# Search for Cython (cython)
#  -> found at /opt/homebrew/bin/cython
# Search for Java compiler (javac)
#  -> found at /usr/bin/javac
# Search for Java keytool (keytool)
#  -> found at /usr/bin/keytool
# Install platform
# Run ['git', 'clone', '-b', 'master', '--single-branch', 'https://github.com/kivy/python-for-android.git', 'python-for-android']
# Cwd /Users/ponponon/Desktop/code/me/ideaboom/.buildozer/android/platform
Cloning into 'python-for-android'...
# Run ['/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/bin/python', '-m', 'pip', 'install', '-q', 'appdirs', 'colorama>=0.3.3', 'jinja2', 'sh>=1.10, <2.0; sys_platform!="win32"', 'build', 'toml', 'packaging', 'setuptools']
# Cwd None
# Apache ANT found at /Users/ponponon/.buildozer/android/platform/apache-ant-1.9.4
# Android SDK found at /Users/ponponon/.buildozer/android/platform/android-sdk
# Recommended android's NDK version by p4a is: 25b
# Android NDK is missing, downloading
# Downloading https://dl.google.com/android/repository/android-ndk-r25b-darwin.zip
Traceback (most recent call last):
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/bin/buildozer", line 8, in <module>
    sys.exit(main())
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/scripts/client.py", line 13, in main
    Buildozer().run_command(sys.argv[1:])
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/__init__.py", line 1024, in run_command
    self.target.run_commands(args)
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/target.py", line 93, in run_commands
    func(args)
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/target.py", line 103, in cmd_debug
    self.buildozer.prepare_for_build()
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/__init__.py", line 172, in prepare_for_build
    self.target.install_platform()
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/targets/android.py", line 615, in install_platform
    self._install_android_ndk()
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/targets/android.py", line 438, in _install_android_ndk
    self.buildozer.download(url,
  File "/Users/ponponon/.local/share/virtualenvs/ideaboom-B0dr_aXc/lib/python3.10/site-packages/buildozer/__init__.py", line 658, in download
    urlretrieve(url, filename, report_hook)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/urllib/request.py", line 1848, in retrieve
    block = fp.read(bs)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tempfile.py", line 483, in func_wrapper
    return func(*args, **kwargs)
ValueError: read of closed file

怎么解决呢?

分析问题所在

首先我是挂了 t 的,所以我先用 requests 下载看看,是不是可以下载成功,看看是在 python 还是在网络

import urllib.request

url = "https://dl.google.com/android/repository/commandlinetools-mac-6514223_latest.zip"
local_filename = "commandlinetools-mac-6514223_latest.zip"

url="https://archive.apache.org/dist/ant/binaries/apache-ant-1.9.4-bin.tar.gz"
local_filename="apache-ant-1.9.4-bin.tar.gz"

try:
    # 直接下载并保存文件
    urllib.request.urlretrieve(url, local_filename)
    print(f"文件已下载: {local_filename}")
except urllib.error.URLError as e:
    print(f"下载失败: {e}")
    

发现是可以下载成功的

但是 buildozer 使用的是 urllib 下载的,所以问题出在 urllib 上吗?

于是写了一个 urllib 版本的

import urllib.request

url = "https://dl.google.com/android/repository/commandlinetools-mac-6514223_latest.zip"
local_filename = "commandlinetools-mac-6514223_latest.zip"

url="https://archive.apache.org/dist/ant/binaries/apache-ant-1.9.4-bin.tar.gz"
local_filename="apache-ant-1.9.4-bin.tar.gz"

try:
    # 直接下载并保存文件
    urllib.request.urlretrieve(url, local_filename)
    print(f"文件已下载: {local_filename}")
except urllib.error.URLError as e:
    print(f"下载失败: {e}")

发现也是可以正常下载的

那问题在于 buildozer 对 urllib 的使用方式了

所以深入扒一下 buildozer 的源代码

发现 buildozer 是使用 urlib 的 FancyURLopener.retrieve 下载的

class ChromeDownloader(FancyURLopener):
    version = (
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
        '(KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36')


urlretrieve = ChromeDownloader().retrieve

关于 FancyURLopener.retrieve 和直接使用 urllib.request.urlretrieve 的区别,我问了一下 ai

图片.png

你代码的问题,核心原因还是出在 FancyURLopener().retrieve 是过时的老方法,它内部对临时文件(比如 tempfile)的处理方式不再适用于现代 Python 的文件流机制,导致

所以把 buildozer 里面的 retrieve 换一下就行?我验证一下

文件路径 site-packages/buildozer/__init__.py

图片.png

结果就可以了

图片.png

安装完成之后如下:

╰─➤  tree -L 4 ~/.buildozer                                                                                                                    
/Users/ponponon/.buildozer
├── android
│   └── platform
│       ├── android
│       │   └── platform
│       ├── android-ndk-r25b
│       │   ├── build
│       │   ├── CHANGELOG.md
│       │   ├── meta
│       │   ├── ndk-build
│       │   ├── ndk-gdb
│       │   ├── ndk-lldb
│       │   ├── ndk-stack
│       │   ├── ndk-which
│       │   ├── NOTICE
│       │   ├── NOTICE.toolchain
│       │   ├── prebuilt
│       │   ├── python-packages
│       │   ├── README.md
│       │   ├── shader-tools
│       │   ├── simpleperf
│       │   ├── source.properties
│       │   ├── sources
│       │   ├── toolchains
│       │   └── wrap.sh
│       ├── android-ndk-r25b-darwin.zip
│       ├── android-sdk
│       │   ├── build-tools
│       │   ├── commandlinetools-mac-6514223_latest.zip
│       │   ├── licenses
│       │   ├── platform-tools
│       │   └── tools
│       └── apache-ant-1.9.4
│           ├── apache-ant-1.9.4
│           └── apache-ant-1.9.4-bin.tar.gz
└── cache
题外话:「使用 FancyURLopener 有什么好处?为什么 buildozer 不直接使用 urllib.request.urlretrieve 而是要用 FancyURLopener?」想知道可以去问 AI

然后,buildozer 已经停止更新了,建议换一个打包工具了

https://pypi.org/project/buildozer/#history

图片.png


universe_king
3.5k 声望716 粉丝