pypi-server
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePyPI Server Setup
PyPI服务器搭建
This skill provides guidance for creating local PyPI servers to host and distribute Python packages.
本技能提供搭建本地PyPI服务器以托管和分发Python包的指导。
When to Use This Skill
适用场景
- Setting up a local PyPI repository or package index
- Building Python packages for distribution (wheel/sdist)
- Serving packages via HTTP for pip installation
- Testing package installation from custom index URLs
- 搭建本地PyPI仓库或包索引
- 构建用于分发的Python包(wheel/sdist格式)
- 通过HTTP提供包服务以支持pip安装
- 测试从自定义索引URL安装包
Environment Reconnaissance (First Step)
环境探查(第一步)
Before planning the approach, gather critical environment information:
-
Check Python version: Runto determine compatibility constraints
python3 --version- Python 3.13+ removed the module, breaking many older tools like
cgipypiserver - Plan fallback strategies based on available Python version
- Python 3.13+ removed the
-
Check available system tools: Verify what utilities exist
- Process management:
which ps pkill lsof kill - Network utilities:
which curl wget nc - Package tools: to see pre-installed packages
pip list
- Process management:
-
Identify port availability: Check if target ports are free before starting servers
在规划实施方案前,先收集关键的环境信息:
-
检查Python版本:运行确定兼容性限制
python3 --version- Python 3.13及以上版本移除了模块,导致
cgi等许多旧工具无法使用pypiserver - 根据可用的Python版本制定备选方案
- Python 3.13及以上版本移除了
-
检查可用的系统工具:确认已安装的实用程序
- 进程管理:
which ps pkill lsof kill - 网络工具:
which curl wget nc - 包管理工具:查看已预装的包
pip list
- 进程管理:
-
确认端口可用性:启动服务器前检查目标端口是否空闲
Approach Selection
方案选择
Decision Framework
决策框架
| Condition | Recommended Approach |
|---|---|
| Python 3.13+ | Use |
| Python 3.12 or earlier | Either |
| Simple single-package hosting | |
| Full PyPI mirroring needed | Consider |
| 条件 | 推荐方案 |
|---|---|
| Python 3.13+ | 使用 |
| Python 3.12或更早版本 | |
| 仅需托管单个简单包 | |
| 需要完整的PyPI镜像 | 考虑使用 |
Recommended Default: Python's Built-in HTTP Server
推荐默认方案:Python内置HTTP服务器
For most local PyPI hosting tasks, use with the correct directory structure. This approach:
python3 -m http.server- Has no external dependencies
- Works across all Python versions
- Is simpler to configure and debug
对于大多数本地PyPI托管任务,建议使用并搭配正确的目录结构。该方案:
python3 -m http.server- 无外部依赖
- 支持所有Python版本
- 配置和调试更简单
Directory Structure Requirements
目录结构要求
Pip expects a specific directory structure when using :
--index-urlserver_root/
└── simple/
└── <package-name>/
└── <package-name>-<version>-py3-none-any.whlCritical Details:
- The directory must be at the root of the served directory
simple/ - Package names in the directory should be normalized (lowercase, hyphens to underscores for some cases)
- The server must be started from the directory containing , not from within it
simple/
使用时,pip要求特定的目录结构:
--index-urlserver_root/
└── simple/
└── <package-name>/
└── <package-name>-<version>-py3-none-any.whl关键细节:
- 目录必须位于服务器根目录下
simple/ - 目录中的包名需要规范化(小写,部分情况下将下划线替换为连字符)
- 必须从包含的目录启动服务器,而不是从
simple/目录内部启动simple/
Building Python Packages
构建Python包
Standard Package Structure
标准包结构
package_name/
├── setup.py
├── pyproject.toml (optional but recommended)
└── package_name/
├── __init__.py
└── module.pypackage_name/
├── setup.py
├── pyproject.toml (optional but recommended)
└── package_name/
├── __init__.py
└── module.pyMinimal setup.py Example
最简setup.py示例
python
from setuptools import setup, find_packages
setup(
name="package-name",
version="0.1.0",
packages=find_packages(),
)python
from setuptools import setup, find_packages
setup(
name="package-name",
version="0.1.0",
packages=find_packages(),
)Build Commands
构建命令
bash
undefinedbash
undefinedBuild wheel and source distribution
Build wheel and source distribution
python3 -m pip install build
python3 -m build
python3 -m pip install build
python3 -m build
Output appears in dist/
Output appears in dist/
undefinedundefinedServer Setup Steps
服务器搭建步骤
Step 1: Create Directory Structure
步骤1:创建目录结构
bash
mkdir -p pypi-server/simple/packagename/
cp dist/*.whl pypi-server/simple/packagename/bash
mkdir -p pypi-server/simple/packagename/
cp dist/*.whl pypi-server/simple/packagename/Step 2: Start HTTP Server
步骤2:启动HTTP服务器
bash
cd pypi-server
python3 -m http.server 8080Important: Start the server from the directory that contains , not from within .
simple/simple/bash
cd pypi-server
python3 -m http.server 8080注意: 必须从包含的目录启动服务器,而不是从目录内部启动。
simple/simple/Step 3: Verify Server
步骤3:验证服务器
Test that the structure is correct:
bash
curl http://localhost:8080/simple/
curl http://localhost:8080/simple/packagename/测试目录结构是否正确:
bash
curl http://localhost:8080/simple/
curl http://localhost:8080/simple/packagename/Verification Strategy
验证策略
Pre-Installation Checks
安装前检查
- Verify server is running:
curl -I http://localhost:PORT/ - Verify simple index exists:
curl http://localhost:PORT/simple/ - Verify package directory exists:
curl http://localhost:PORT/simple/packagename/ - Verify wheel file is accessible:
curl -I http://localhost:PORT/simple/packagename/file.whl
- 验证服务器是否运行:
curl -I http://localhost:PORT/ - 验证simple索引是否存在:
curl http://localhost:PORT/simple/ - 验证包目录是否存在:
curl http://localhost:PORT/simple/packagename/ - 验证wheel文件是否可访问:
curl -I http://localhost:PORT/simple/packagename/file.whl
Installation Test
安装测试
bash
pip install --index-url http://localhost:PORT/simple packagename==versionbash
pip install --index-url http://localhost:PORT/simple packagename==versionPost-Installation Verification
安装后验证
python
import packagenamepython
import packagenameTest core functionality
Test core functionality
undefinedundefinedCommon Pitfalls and Solutions
常见问题与解决方案
1. Port Already in Use
1. 端口已被占用
Symptom:
OSError: [Errno 98] Address already in useSolutions:
- Use a different port
- Find and kill the existing process:
python
import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - Create a custom server script with option
SO_REUSEADDR
症状:
OSError: [Errno 98] Address already in use解决方案:
- 使用其他端口
- 查找并终止占用端口的进程:
python
import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - 创建带有选项的自定义服务器脚本
SO_REUSEADDR
2. Wrong Directory Structure
2. 目录结构错误
Symptom: when pip tries to access
404 Not Found/simple/Cause: Server started from wrong directory or missing prefix
simple/Solution: Verify the URL returns a directory listing
http://localhost:PORT/simple/症状: pip访问时返回
/simple/404 Not Found原因: 服务器启动目录错误或缺少前缀
simple/解决方案: 验证是否返回目录列表
http://localhost:PORT/simple/3. Python 3.13+ Compatibility
3. Python 3.13+兼容性问题
Symptom: when using pypiserver
ModuleNotFoundError: No module named 'cgi'Cause: Python 3.13 removed the deprecated module
cgiSolution: Use instead of pypiserver
python3 -m http.server症状: 使用pypiserver时出现
ModuleNotFoundError: No module named 'cgi'原因: Python 3.13移除了已弃用的模块
cgi解决方案: 使用替代pypiserver
python3 -m http.server4. Process Management Without Standard Tools
4. 无标准工具时的进程管理
Symptom: Cannot find or kill background processes (ps/pkill not available)
Solutions:
- Use Python's process management:
python
import subprocess proc = subprocess.Popen(['python3', '-m', 'http.server', '8080']) # Save proc.pid for later termination - Use filesystem on Linux:
/procls /proc/*/cmdline - Track PIDs explicitly when starting background processes
症状: 无法查找或终止后台进程(ps/pkill不可用)
解决方案:
- 使用Python的进程管理功能:
python
import subprocess proc = subprocess.Popen(['python3', '-m', 'http.server', '8080']) # Save proc.pid for later termination - 在Linux系统上使用文件系统:
/procls /proc/*/cmdline - 启动后台进程时显式记录PID
5. Shell Compatibility
5. Shell兼容性问题
Symptom: when sourcing files
source: not foundCause: Using in sh shell (source is a bash feature)
sourceSolution: Use instead of for POSIX compatibility:
.sourcebash
. ./venv/bin/activate症状: 执行source命令时出现
source: not found原因: 在sh shell中使用source命令(source是bash的特性)
解决方案: 为了兼容POSIX标准,使用替代:
.sourcebash
. ./venv/bin/activate6. Package Name Normalization
6. 包名规范化问题
Symptom: Package not found despite correct structure
Cause: Pip normalizes package names (underscores to hyphens, lowercase)
Solution: Use lowercase names and be consistent with hyphens/underscores
症状: 目录结构正确但找不到包
原因: Pip会对包名进行规范化处理(下划线替换为连字符,转为小写)
解决方案: 使用小写包名,保持连字符/下划线的一致性
Custom Server Script (Robust Alternative)
自定义服务器脚本(更可靠的替代方案)
For better process control and port reuse, consider a custom server script:
python
#!/usr/bin/env python3
import http.server
import socketserver
import os
PORT = 8080
DIRECTORY = "/path/to/pypi-server"
os.chdir(DIRECTORY)
class ReuseAddrServer(socketserver.TCPServer):
allow_reuse_address = True
handler = http.server.SimpleHTTPRequestHandler
with ReuseAddrServer(("", PORT), handler) as httpd:
print(f"Serving at port {PORT}")
httpd.serve_forever()为了更好地控制进程和实现端口复用,可以使用自定义服务器脚本:
python
#!/usr/bin/env python3
import http.server
import socketserver
import os
PORT = 8080
DIRECTORY = "/path/to/pypi-server"
os.chdir(DIRECTORY)
class ReuseAddrServer(socketserver.TCPServer):
allow_reuse_address = True
handler = http.server.SimpleHTTPRequestHandler
with ReuseAddrServer(("", PORT), handler) as httpd:
print(f"Serving at port {PORT}")
httpd.serve_forever()Checklist Before Starting
启动前检查清单
- Verified Python version and tool compatibility
- Created correct directory structure with prefix
simple/ - Built package successfully (wheel exists in dist/)
- Copied wheel to correct location under
simple/packagename/ - Confirmed target port is available
- Plan for process management (how to stop the server later)
- 已验证Python版本和工具兼容性
- 已创建带前缀的正确目录结构
simple/ - 已成功构建包(dist/目录下存在wheel文件)
- 已将wheel文件复制到下的正确位置
simple/packagename/ - 已确认目标端口可用
- 已规划进程管理方案(后续如何停止服务器)