跳转到主要内容

一个用于与pip/easy_install一起使用的最小PyPI服务器。

项目描述

pypi server logo

pypiserver - 与pip/easy_install一起使用的最小PyPI服务器

pypi badge ci workflow Generic badge Generic badge

名称 描述
版本 2.2.0
日期 2024-09-15
来源 https://github.com/pypiserver/pypiserver
PyPI https://pypi.ac.cn/project/pypiserver/
测试 https://github.com/pypiserver/pypiserver/actions
维护者 @ankostis, @mplanchard, @dee-me-tree-or-love, @pawamoy, 新成员? 我们欢迎新的维护者! #397
许可证 zlib/libpng + MIT
社区 https://pypiserver.zulipchat.com

[!TIP] 在 讨论 中提问,或在 Zulip 上与我们聊天

pypiserver 是一个与 PyPI 兼容的最小服务器,适用于 pipeasy_install。它基于 bottle,并从常规目录中提供软件包。可以使用 pipsetuptoolstwinepypi-uploader 或简单地使用 scp 来上传Wheels、bdists、eggs及其相应的PGP签名。

[!Note] 推动官方 PyPI 的软件是 Warehouse。然而,Warehouse 是相当专业化的,专门用于 pypi.org 的软件,不应在其他上下文中使用。特别是,它不支持作为自定义包索引供用户自己提供软件包。

pypiserver 实现了与 PyPI 相同的接口,允许标准 Python 打包工具,如 piptwine,将其作为包索引与之交互,就像它们与 PyPI 交互一样,同时使得运行索引服务器变得更加容易。

pypiserver

目录

快速入门:安装和使用

pypiserver 与 Python 3.6+ 和 PyPy3 兼容。

较旧的Python版本可能仍然可以使用,但未经过测试。

对于旧版Python,请使用 pypiserver-1.x 系列。请注意,这些不受官方支持,并且不会收到错误修复或新功能。

[!TIP]

以下命令在具有posix shell的类Unix操作系统上运行。字符 '~' 展开为用户的家目录。

如果您使用的是Windows操作系统,您将需要使用他们的“Windows兼容版本”。本文档中的其余部分也是如此。

  1. 使用以下命令安装 pypiserver

    pip install pypiserver                # Or: pypiserver[passlib,cache]
    mkdir ~/packages                      # Copy packages into this directory.
    

    [!TIP] 请参阅 替代安装方法

  2. 将一些包复制到您的 ~/packages 文件夹,然后启动并运行 pypiserver

    pypi-server run -p 8080 ~/packages &      # Will listen to all IPs.
    
  3. 从客户端计算机,输入以下内容

    # Download and install hosted packages.
    pip install --extra-index-url http://localhost:8080/simple/ ...
    
    # or
    pip install --extra-index-url http://localhost:8080 ...
    
    # Search hosted packages.
    pip search --index http://localhost:8080 ...
    
    # Note that pip search does not currently work with the /simple/ endpoint.
    

    [!TIP] 请参阅 客户端配置 以避免繁琐的输入。

  4. 在cmd行中输入 pypi-server -h 来打印详细的用法信息

    usage: pypi-server [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                      [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                      [--backend {auto,simple-dir,cached-dir}] [--version]
                      {run,update} ...
    
    start PyPI compatible package server serving packages from PACKAGES_DIRECTORY. If PACKAGES_DIRECTORY is not given on the command line, it uses the default ~/packages. pypiserver scans this directory recursively for packages. It skips packages and directories starting with a dot. Multiple package directories may be specified.
    
    positional arguments:
      {run,update}
        run                 Run pypiserver, serving packages from
                            PACKAGES_DIRECTORY
        update              Handle updates of packages managed by pypiserver. By
                            default, a pip command to update the packages is
                            printed to stdout for introspection or pipelining. See
                            the `-x` option for updating packages directly.
    
    optional arguments:
      -h, --help            show this help message and exit
      -v, --verbose         Enable verbose logging; repeat for more verbosity.
      --log-file FILE       Write logging info into this FILE, as well as to
                            stdout or stderr, if configured.
      --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                            stdout, stderr, and none
      --log-frmt FORMAT     The logging format-string.  (see `logging.LogRecord`
                            class from standard python library)
      --hash-algo HASH_ALGO
                            Any `hashlib` available algorithm to use for
                            generating fragments on package links. Can be disabled
                            with one of (0, no, off, false).
      --backend {auto,simple-dir,cached-dir}
                            A backend implementation. Keep the default 'auto' to
                            automatically determine whether to activate caching or
                            not
      --version             show program's version number and exit
    
    Visit https://github.com/pypiserver/pypiserver for more information
    

关于pypi服务器运行的更多详细信息

在cmd行中输入 pypi-server run -h 来打印详细的用法信息

usage: pypi-server run [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                       [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                       [--backend {auto,simple-dir,cached-dir}] [--version]
                       [-p PORT] [-i HOST] [-a AUTHENTICATE]
                       [-P PASSWORD_FILE] [--disable-fallback]
                       [--fallback-url FALLBACK_URL]
                       [--health-endpoint HEALTH_ENDPOINT] [--server METHOD]
                       [-o] [--welcome HTML_FILE] [--cache-control AGE]
                       [--log-req-frmt FORMAT] [--log-res-frmt FORMAT]
                       [--log-err-frmt FORMAT]
                       [package_directory [package_directory ...]]

positional arguments:
  package_directory     The directory from which to serve packages.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enable verbose logging; repeat for more verbosity.
  --log-file FILE       Write logging info into this FILE, as well as to
                        stdout or stderr, if configured.
  --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                        stdout, stderr, and none
  --log-frmt FORMAT     The logging format-string.  (see `logging.LogRecord`
                        class from standard python library)
  --hash-algo HASH_ALGO
                        Any `hashlib` available algorithm to use for
                        generating fragments on package links. Can be disabled
                        with one of (0, no, off, false).
  --backend {auto,simple-dir,cached-dir}
                        A backend implementation. Keep the default 'auto' to
                        automatically determine whether to activate caching or
                        not
  --version             show program's version number and exit
  -p PORT, --port PORT  Listen on port PORT (default: 8080)
  -i HOST, -H HOST, --interface HOST, --host HOST
                        Listen on interface INTERFACE (default: 0.0.0.0)
  -a AUTHENTICATE, --authenticate AUTHENTICATE
                        Comma-separated list of (case-insensitive) actions to
                        authenticate (options: download, list, update;
                        default: update).
                         
                         Any actions not specified are not authenticated, so
                         to authenticate downloads and updates, but allow
                         unauthenticated viewing of the package list, you would
                         use:
                         
                          pypi-server -a 'download, update' -P
                          ./my_passwords.htaccess
                         
                        To disable authentication, use:
                         
                          pypi-server -a . -P .
                         
                        See the `-P` option for configuring users and
                        passwords.
                         
                        Note that when uploads are not protected, the
                        `register` command is not necessary, but `~/.pypirc`
                        still needs username and password fields, even if
                        bogus.
  -P PASSWORD_FILE, --passwords PASSWORD_FILE
                        Use an apache htpasswd file PASSWORD_FILE to set
                        usernames and passwords for authentication.
                         
                        To allow unauthorized access, use:
                         
                          pypi-server -a . -P .
                         
  --disable-fallback    Disable the default redirect to PyPI for packages not
                        found in the local index.
  --fallback-url FALLBACK_URL
                        Redirect to FALLBACK_URL for packages not found in the
                        local index.
  --health-endpoint HEALTH_ENDPOINT
                        Configure a custom liveness endpoint. It always
                        returns 200 Ok if the service is up. Otherwise, it
                        means that the service is not responsive.
  --server METHOD       Use METHOD to run the server. Valid values include
                        paste, cherrypy, twisted, gunicorn, gevent, wsgiref,
                        and auto. The default is to use "auto", which chooses
                        one of paste, cherrypy, twisted, or wsgiref.
  -o, --overwrite       Allow overwriting existing package files during
                        upload.
  --welcome HTML_FILE   Use the contents of HTML_FILE as a custom welcome
                        message on the home page.
  --cache-control AGE   Add "Cache-Control: max-age=AGE" header to package
                        downloads. Pip 6+ requires this for caching.AGE is
                        specified in seconds.
  --log-req-frmt FORMAT
                        A format-string selecting Http-Request properties to
                        log; set to '%s' to see them all.
  --log-res-frmt FORMAT
                        A format-string selecting Http-Response properties to
                        log; set to '%s' to see them all.
  --log-err-frmt FORMAT
                        A format-string selecting Http-Error properties to
                        log; set to '%s' to see them all.

关于pypi-server更新的更多详细信息

关于 pypi-server update 的更多详细信息

usage: pypi-server update [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                          [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                          [--backend {auto,simple-dir,cached-dir}] [--version]
                          [-x] [-d DOWNLOAD_DIRECTORY] [-u]
                          [--blacklist-file IGNORELIST_FILE]
                          [package_directory [package_directory ...]]

positional arguments:
  package_directory     The directory from which to serve packages.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enable verbose logging; repeat for more verbosity.
  --log-file FILE       Write logging info into this FILE, as well as to
                        stdout or stderr, if configured.
  --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                        stdout, stderr, and none
  --log-frmt FORMAT     The logging format-string. (see `logging.LogRecord`
                        class from standard python library)
  --hash-algo HASH_ALGO
                        Any `hashlib` available algorithm to use for
                        generating fragments on package links. Can be disabled
                        with one of (0, no, off, false).
  --backend {auto,simple-dir,cached-dir}
                        A backend implementation. Keep the default 'auto' to
                        automatically determine whether to activate caching or
                        not
  --version             show program's version number and exit
  -x, --execute         Execute the pip commands rather than printing to
                        stdout
  -d DOWNLOAD_DIRECTORY, --download-directory DOWNLOAD_DIRECTORY
                        Specify a directory where packages updates will be
                        downloaded. The default behavior is to use the
                        directory which contains the package being updated.
  -u, --allow-unstable  Allow updating to unstable versions (alpha, beta, rc,
                        dev, etc.)
  --blacklist-file IGNORELIST_FILE, --ignorelist-file IGNORELIST_FILE
                        Don't update packages listed in this file (one package
                        name per line, without versions, '#' comments
                        honored). This can be useful if you upload private
                        packages into pypiserver, but also keep a mirror of
                        public packages that you regularly update. Attempting
                        to pull an update of a private package from `pypi.org`
                        might pose a security risk - e.g. a malicious user
                        might publish a higher version of the private package,
                        containing arbitrary code.

客户端配置

始终在命令行中指定pypi URL有些繁琐。由于 pypiserver 在没有请求的包时将 pip/easy_install 重定向到 pypi.org 索引,因此将其配置为始终使用您本地的pypi索引是一个好主意。

配置pip

对于 pip 命令,您可以通过设置环境变量 PIP_EXTRA_INDEX_URL 在您的 .bashr/.profile/.zshrc 中来完成

export PIP_EXTRA_INDEX_URL=http://localhost:8080/simple/

或者通过添加以下行到 ~/.pip/pip.conf

[global]
extra-index-url = http://localhost:8080/simple/

[!NOTE]

如果您在没有 https 的远程URL上安装了 pypiserver,您将收到来自 pip 的“不受信任”警告,敦促您添加 --trusted-host 选项。您也可以将此选项永久添加到您的配置文件或环境变量中。

配置easy_install

对于 easy_install 命令,您可以在 ~/.pydistutils.cfg 中设置以下配置

[easy_install]
index_url = http://localhost:8080/simple/

远程上传软件包

您可以直接将包复制到服务器的文件夹中(例如,使用 scp),也可以使用Python工具来完成这项任务,例如 python setup.py upload。在这种情况下,pypiserver 负责验证上传请求。

[!NOTE]

我们强烈建议对上传进行 密码保护

您可以选择禁用上传的认证(例如,在内部网络中)。为了避免草率的保安决定,请阅读有关 -P-a 选项的帮助。

Apache样认证(htpasswd)

  1. 首先确保您已安装了 passlib 模块(请注意,需要 passlib>=1.6),这是解析由 -P--passwords 选项指定的 Apache htpasswd 文件所需的,见以下步骤。

        pip install passlib
    
  2. 使用以下命令创建 Apache htpasswd 文件,至少包含一个用户/密码对(您将需要输入密码)

        htpasswd -sc htpasswd.txt <some_username>
    

[!TIP]

阅读此 SO 问题,了解在 Windows 下运行 htpasswd 命令或如果您对内部服务的密码不关心(从保安角度看仍然是“不好”)的密码无效时,您可以使用此 公共服务

[!TIP]

通过API访问 pypiserver 时,可以通过 auther 配置标志提供替代认证方法。任何返回布尔值的可调用对象都可以传递给 pypiserver 配置,以提供自定义认证。例如,要配置 pypiserver 使用 python-pam

    import pam
    pypiserver.default_config(auther=pam.authenticate)

请参阅 使用临时代理认证提供程序 获取更多信息。

  1. 您只需要重新启动服务器一次带有 -P 选项(但稍后可以动态添加或更新用户/密码对)

        ./pypi-server run -p 8080 -P htpasswd.txt ~/packages &
    

使用setuptools上传

  1. 在客户端,编辑或创建一个包含类似内容的 ~/.pypirc 文件

        [distutils]
        index-servers =
          pypi
          local
    
        [pypi]
        username:<your_pypi_username>
        password:<your_pypi_passwd>
    
        [local]
        repository: http://localhost:8080
        username: <some_username>
        password: <some_passwd>
    
  2. 然后从您希望上传的 Python 项目的目录中,运行以下命令

        python setup.py sdist upload -r local
    

使用twine上传

为了避免将您的密码以明文形式存储在磁盘上,您可以选择以下方法之一

  • 使用带有 -r 选项的 register setuptools 的命令,如下所示

      python setup.py sdist register -r local upload -r local
    
  • 使用 twine 库,它将过程分为两个步骤。此外,它支持使用 PGP-Signatures 签名您的文件,并将生成的 .asc 文件上传到 pypiserver

      twine upload -r local --sign -identity user_name ./foo-1.zip
    

使用Docker镜像

从版本1.2.5开始,每次向master、每个dev、alpha或beta发布以及每个最终发布推送都会构建官方的Docker镜像。最新完整发布版本始终可以在标签latest下找到,而当前master分支始终可以在标签unstable下找到。

您可以在我们的Docker仓库查看当前可用的所有标签。

要使用Docker运行最新版本的pypiserver,只需

    docker run pypiserver/pypiserver:latest run

这将在容器内启动从/data/packages目录服务软件包的pypiserver,监听容器端口8080。

容器接受与正常pypi-server可执行文件相同的所有参数,除了内部容器端口(-p),它始终为8080。

当然,仅仅运行容器并不那么有趣。要将主机上的端口80映射到容器的端口8080:

    docker run -p 80:8080 pypiserver/pypiserver:latest run

您现在可以在网页浏览器中通过localhost:80访问您的pypiserver

要从主机上的目录(例如,~/packages)提供服务包:

    docker run -p 80:8080 -v ~/packages:/data/packages pypiserver/pypiserver:latest run

要针对本地.htpasswd文件进行身份验证:

    docker run -p 80:8080 -v ~/.htpasswd:/data/.htpasswd pypiserver/pypiserver:latest run -P .htpasswd packages

您还可以指定使用Docker服务运行pypiserver,使用composefile。一个示例composefile提供如下

替代安装方法

在尝试以下方法之前,首先使用以下命令检查是否已存在pypiserver的先前版本,并(可选)卸载它们:

# VERSION-CHECK: Fails if not installed.
pypi-server --version

# UNINSTALL: Invoke again until it fails.
pip uninstall pypiserver

安装最新版本

如果pypi中的最新版本是预发布版本,您必须使用pip--pre选项。要更新现有安装,请结合使用--ignore-installed

pip install pypiserver --pre -I

假设您在PATH上已安装git,您可以直接使用以下命令从github安装最新的pypiserver

pip install git+git://github.com/pypiserver/pypiserver.git

配方

管理包目录

pypi-server命令有update命令,可以搜索可用软件包的更新。它扫描软件包目录以查找可用软件包,并在pypi.org上搜索更新。如果没有进一步选项,pypi-server update将只打印必须运行的命令列表,以获取每个软件包的最新版本。输出如下

$ ./pypi-server update 
checking 106 packages for newer version

.........u.e...........e..u.............
.....e..............................e...
..........................

no releases found on pypi for PyXML, Pymacs, mercurial, setuptools

# update raven from 1.4.3 to 1.4.4
pip -q install --no-deps  --extra-index-url https://pypi.ac.cn/simple/ -d /home/ralf/packages/mirror raven==1.4.4

# update greenlet from 0.3.3 to 0.3.4
pip -q install --no-deps  --extra-index-url https://pypi.ac.cn/simple/ -d /home/ralf/packages/mirror greenlet==0.3.4

它首先打印出每个软件包在pypi上检查到的可用版本后的单个字符。点(.)表示软件包是最新的,'u'表示软件包可以更新,'e'表示pypi上的发布列表为空。之后,它显示一个可以用于更新单个软件包的pip命令行。要么复制粘贴该命令,要么运行pypi-server update -x来真正执行这些命令。但是,您需要安装pip才能使这生效。

指定附加的-u选项也将允许下载alpha、beta和发布候选版本。如果没有此选项,则不会考虑这些版本。

提供数千个软件包

[!IMPORTANT] 默认情况下,pypiserver在每次发生传入HTTP请求时都会扫描整个软件包目录。对于少量软件包来说这没问题,但当服务数千个软件包时,会导致明显的速度减慢。

如果您遇到这个问题,可以通过启用pypiserver的目录缓存功能来获得显著的加速。唯一的要求是安装watchdog软件包,或者可以在安装pypiserver时安装,通过指定cache额外选项:

pip install pypiserver[cache]

通过使用您的Web服务器内建的缓存功能可以获得额外的加速。例如,如果您正在使用以下Behind a reverse proxy中描述的nginx作为反向代理,您可以轻松启用缓存。例如,要允许nginx缓存最多10GB数据,最多1小时:

proxy_cache_path /data/nginx/cache
                  levels=1:2
                  keys_zone=pypiserver_cache:10m
                  max_size=10g
                  inactive=60m
                  use_temp_path=off;

server {
    # ...
    location / {
        proxy_cache pypiserver_cache;
        proxy_pass http://localhost:8080;
    }
}

[!TIP] 使用Web服务器缓存特别有助于您有高请求量。使用nginx缓存,一个实际的pypiserver安装能够轻松支持在高峰负载时每分钟超过1000个软件包的下载。

管理自动化启动

在系统启动时自动启动pypiserver有多种选择。其中两种最常见的是Linux系统的systemdsupervisor。对于Windows系统,如果没有第三方工具如NSSM,创建服务并不是一件容易的事情。

作为systemd服务运行

systemd是大多数现代Linux系统默认安装的,因此它是一个管理pypiserver进程的优秀选项。以下是一个systemd的示例配置文件:

[Unit]
Description=A minimal PyPI server for use with pip/easy_install.
After=network.target

[Service]
Type=simple
# systemd requires absolute path here too.
PIDFile=/var/run/pypiserver.pid
User=www-data
Group=www-data

ExecStart=/usr/local/bin/pypi-server run -p 8080 -a update,download --log-file /var/log/pypiserver.log -P /etc/nginx/.htpasswd /var/www/pypi
ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID
Restart=always

WorkingDirectory=/var/www/pypi

TimeoutStartSec=3
RestartSec=5

[Install]
WantedBy=multi-user.target

调整路径并将此文件作为pypiserver.service添加到您的systemd/system目录中,将允许您使用systemctl管理pypiserver进程,例如systemctl start pypiserver

更多关于systemd的有用信息可以在以下网址找到:https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units

通过supervisor启动

supervisor的优点是它是一个纯Python包,因此它为进程管理提供了出色的跨平台支持。以下是一个supervisor的示例配置文件:

[program:pypi]
command=/home/pypi/pypi-venv/bin/pypi-server run -p 7001 -P /home/pypi/.htpasswd /home/pypi/packages
directory=/home/pypi
user=pypi
autostart=true
autorestart=true
stderr_logfile=/var/log/pypiserver.err.log
stdout_logfile=/var/log/pypiserver.out.log

然后,可以通过supervisord使用supervisorctl来管理进程。

使用NSSM作为服务运行

对于Windows,从https://nssm.cc下载NSSM,解压到如Program Files等期望的位置。决定您要使用win32还是win64,并将该exe添加到环境变量PATH中。

创建一个start_pypiserver.bat文件

pypi-server run -p 8080 C:\Path\To\Packages &

[!TIP] 在创建服务之前先运行批处理文件进行测试。确保您可以远程访问服务器并安装包。如果可以,请继续,如果不能,请调试直到您可以为止。这将确保在将NSSM添加到混合之前,您知道服务器正在运行。

从命令提示符

nssm install pypiserver

此命令将启动一个NSSM图形界面应用程序

Path: C:\Path\To\start_pypiserver.bat
Startup directory: Auto generates when selecting path
Service name: pypiserver

还有更多标签,但这只是一个基本设置。如果服务需要以特定的登录凭据运行,请确保在登录标签中输入这些凭据。

启动服务

nssm start pypiserver

[!TIP] 其他有用的命令

nssm --help
nssm stop <servicename>
nssm restart <servicename>
nssm status <servicename>

有关详细信息,请访问https://nssm.cc

使用不同的WSGI服务器

  • bottle web服务器支持许多WSGI服务器,包括pastecherrypytwistedwsgiref(Python的一部分);您可以通过使用--server标志来选择它们。

  • 您可以使用以下交互式代码查看所有支持的WSGI服务器:

    >>> from pypiserver import bottle
    >>> list(bottle.server_names.keys())
    ['cgi', 'gunicorn', 'cherrypy', 'eventlet', 'tornado', 'geventSocketIO',
    'rocket', 'diesel', 'twisted', 'wsgiref', 'fapws3', 'bjoern', 'gevent',
    'meinheld', 'auto', 'aiohttp', 'flup', 'gae', 'paste', 'waitress']
    
  • 如果上述任何服务器都不符合您的需求,只需调用pypiserver:app()方法,该方法返回内部WSGI应用程序(不启动服务器) - 您可以将其发送到任何您喜欢的WSGI服务器。请参阅利用API部分。

  • 以下是一些示例 - 您可以在bottle网站中找到更多详细信息。

Apache

要使用您的Apache2pypiserver,最好使用mod_wsgi,如bottle文档中所述。

[!NOTE] 如果您选择使用mod_proxy,请注意,您可能会遇到前缀路径的问题(见#155)。

  1. 根据需要将以下Apache配置文件放置在顶层作用域内,或放在某个<VirtualHost>内部(由Thomas Waldmann贡献):

    WSGIScriptAlias   /     /yoursite/wsgi/pypiserver-wsgi.py
    WSGIDaemonProcess       pypisrv user=pypisrv group=pypisrv umask=0007 \
                            processes=1 threads=5 maximum-requests=500 \
                            display-name=wsgi-pypisrv inactivity-timeout=300
    WSGIProcessGroup        pypisrv
    WSGIPassAuthorization On    # Required for authentication (https://github.com/pypiserver/pypiserver/issues/288)
    
    <Directory /yoursite/wsgi >
        Require all granted
    </Directory>
    

    或者,如果使用较旧的Apache < 2.4,将最后一部分替换为以下内容:

    <Directory /yoursite/wsgi >
        Order deny,allow
        Allow from all
    </Directory>
    
  2. 然后创建/yoursite/cfg/pypiserver.wsgi文件,并确保WSGIDaemonProcess指令(例如示例中的pypisrv:pypisrv)的usergroup对该文件有读取权限。

    import pypiserver
    
    conf = pypiserver.default_config(
        root =          "/yoursite/packages",
        password_file = "/yoursite/htpasswd", )
    application = pypiserver.app(**conf)
    

    [!提示] 如果您在虚拟环境中安装了 pypiserver,请遵循 mod_wsgi说明,并在上面的 Python 代码前面添加以下内容

    import site
    
    site.addsitedir('/yoursite/venv/lib/pythonX.X/site-packages')
    

[!注意] 由于安全原因,请注意 Directory 指令仅授予对包含 wsgi 启动脚本的目录的访问权限;没有其他权限。

[!注意] 要在 Apache 上启用 HTTPS 支持,请配置包含 WSGI 配置的指令以使用 SSL。

gunicorn

以下命令使用 gunicorn 启动 pypiserver

gunicorn -w4 'pypiserver:app(root="/home/ralf/packages")'

或者当使用多个根目录时

gunicorn -w4 'pypiserver:app(root=["/home/ralf/packages", "/home/ralf/experimental"])'

paste

paste 允许在不同的 URL 路径下运行多个 WSGI 应用程序。因此,可以在不同的路径上提供不同的软件包集。

以下示例 paste.ini 可以用于在不同的路径上提供稳定和不稳定的软件包

  [composite:main]
  use = egg:Paste#urlmap
  /unstable/ = unstable
  / = stable

  [app:stable]
  use = egg:pypiserver#main
  root = ~/stable-packages

  [app:unstable]
  use = egg:pypiserver#main
  root = ~/stable-packages
      ~/unstable-packages

  [server:main]
  use = egg:gunicorn#main
  host = 0.0.0.0
  port = 9000
  workers = 5
  accesslog = -

[!注意] 为了使此功能正常工作,您需要安装一些额外的依赖项,例如:

pip install paste pastedeploy gunicorn pypiserver

然后服务器可以启动

gunicorn_paster paste.ini

在反向代理后面

您还可以在反向代理后面运行 pypiserver

Nginx

扩展您的 nginx 配置

upstream pypi {
  server              pypiserver.example.com:12345 fail_timeout=0;
}

server {
  server_name         myproxy.example.com;

  location / {
    proxy_set_header  Host $host:$server_port;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_pass        http://pypi;
  }
}

从 pypiserver 1.3 版本开始,您还可以在反向代理配置中使用 X-Forwarded-Host 标头以启用更改基本 URL。例如,如果您想在服务器上的特定路径下托管 pypiserver

upstream pypi {
  server              localhost:8000;
}

server {
  location /pypi/ {
      proxy_set_header  X-Forwarded-Host $host:$server_port/pypi;
      proxy_set_header  X-Forwarded-Proto $scheme;
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header  X-Real-IP $remote_addr;
      proxy_pass        http://pypi;
  }
}

支持HTTPS

使用反向代理是将 pypiserver 放在 HTTPS 后面的首选方法。例如,要使用 nginx 在端口 443 上将 pypiserver 放在 HTTPS 后面,并自动进行 HTTP 重定向

upstream pypi {
  server               localhost:8000;
}

server {
  listen              80 default_server;
  server_name         _;
  return              301 https://$host$request_uri;
}

server {
  listen              443 ssl;
  server_name         pypiserver.example.com;

  ssl_certificate     /etc/star.example.com.crt;
  ssl_certificate_key /etc/star.example.com.key;
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;

  location / {
    proxy_set_header  Host $host:$server_port;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_pass        http://pypi;
  }
}

[!提示] 请参阅 nginx 的 HTTPS 文档 以获取更多详细信息。

使用,例如,certbot 和 letsencrypt 可以简化获取和保持证书更新的过程。

Traefik

您还可以使用 Traefik 将 pypiserver 放在 HTTPS 端口 443 后面,并使用 Docker Compose 自动进行 HTTP 重定向。有关更多信息,请参阅提供的docker-compose.yml 示例。

利用API

为了启用临时的认证提供程序或使用 bottle 不直接支持的 WSGI 服务器,您需要通过其 API 启动 pypiserver

  • 配置 pypiserver 的主要入口点是 pypiserver:app() 函数。此函数返回内部 WSGI 应用程序,然后您可以将它发送到您喜欢的任何 WSGI 服务器。

  • 要获取所有 pypiserver:app() 关键字及其说明,请阅读 pypiserver:default_config() 函数。

  • 最后,要启动配置的应用程序,请调用 bottle:run(app, host, port, server) 函数。请注意,pypiserver 随附有其自己的 bottle 版本;要使用它,请按如下方式导入:from pypiserver import bottle

使用临时的认证提供者

只能使用 API 设置 pypiserver:app() 函数的 auther 关键字。这可以是任何在传递 usernamepassword 给它时返回布尔值的可调用对象。

例如,要基于 Unix 下的 /etc/passwd 文件进行用户认证,您可以通过以下步骤将这些决策委托给 python-pam

  1. 确保安装了 python-pam 模块

    pip install python-pam
    
  2. 创建一个符合以下模式的 Python 脚本

    $ cat > pypiserver-start.py
    import pypiserver
    from pypiserver import bottle
    import pam
    app = pypiserver.app(root='./packages', auther=pam.authenticate)
    bottle.run(app=app, host='0.0.0.0', port=80, server='auto')
    
    [Ctrl+ D]
    
  3. 调用 Python 脚本来启动 pypiserver

    python pypiserver-start.py
    

[注意] python-pam 模块需要读取 /etc/shadow 文件;您可以添加 pypiserver 运行的用户到 shadow 用户组,使用以下命令: sudo usermod -a -G shadow pypy-user

与MicroPython一起使用

MicroPython 解释器可以为嵌入式设备安装包,使用模块 upip.py。此模块使用专用的 json-endpoint 来检索包信息。此端点由 pypiserver 支持。

可以使用 micropython 的 UNIX 端口进行测试

cd micropython
ports/unix/micropython -m tools.upip install -i http://my-server:8080 -p /tmp/mymodules micropython-foobar

从嵌入式设备的 REPL 安装包的方式如下

import network
import upip

sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('<your ESSID>', '<your password>')
upip.index_urls = ["http://my-server:8080"]
upip.install("micropython-foobar")

关于 micropython 打包的更多信息,请参阅此处: https://docs.micropython.org/en/latest/reference/packages.html

自定义健康检查端点

pypiserver/health 提供默认的健康端点。如果服务正常运行,它总是返回 200 Ok。否则,表示该服务无响应。

此外,pypiserver 允许用户自定义健康端点。允许使用字母数字字符、连字符、正斜杠和下划线,且端点不应与任何现有路由重叠。有效示例:/healthz/health/live-1/api_health/action/health

通过CLI参数配置自定义健康端点

使用 --health-endpoint 参数运行 pypiserver

pypi-server run --health-endpoint /action/health

通过脚本配置自定义健康端点

import pypiserver
from pypiserver import bottle
app = pypiserver.app(root="./packages", health_endpoint="/action/health")
bottle.run(app=app, host="0.0.0.0", port=8080, server="auto")

尝试 curl http://localhost:8080/action/health

来源

要创建仓库的副本,使用

git clone https://github.com/pypiserver/pypiserver.git
cd pypiserver

要接收上述文件夹中的任何后续更改,使用

git pull

已知限制

[重要] pypiserver 并未实现如 PyPI 所见到的完整 API。它仅实现了使 easy_installpip install搜索 工作所需的最小功能。

以下为已知的限制

  • 比较上传的包和 pypi 以查看是否过时的 pypi -U 命令不尊重 http-proxy 环境变量(见 #19)。
  • 它接受文档上传,但不将其保存到磁盘(见 #47 中的讨论)。
  • 它不处理拼写错误的包,如 pypi-repo 所做的那样,因此建议使用 --extra-index-url 而不是 --index-url(见 #38)。

请使用 Github 的 bugtracker 报告其他发现的错误。

类似项目

有很多其他项目,允许您运行自己的 PyPI 服务器。如果 pypiserver 对您不起作用,以下是最受欢迎的替代方案之一

未维护或存档

这些项目曾是 pypiserver 的替代方案,但现在它们要么不再维护,要么已存档。

  • pip2pi:一个简单的命令行工具,它从 pip 要求构建一个兼容 PyPI 的本地文件夹

  • flask-pypi-proxy:一个 PyPI 代理,同时允许上传自定义包

相关软件

以下列出了一些与 pypiserver 作为索引服务器使用直接相关的软件项目,您可能希望熟悉它们

  • pypi-uploader:一个命令行工具,用于从 PyPI 上传包到您的 pypiserver,而无需首先在本地存储它们。

  • twine:一个命令行工具,用于与 PyPI 或 pypiserver 交互。

  • warehouse:为 PyPI 提供动力的软件。它通常不打算由最终用户运行。

许可

PyPI服务器 包含一个 MIT 许可下的 bottle 的副本,其余部分采用 zlib/libpng 许可证分发。请参阅 LICENSE.txt 文件。

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解有关 安装包 的更多信息。

源代码分发

pypiserver-2.2.0.tar.gz (190.1 kB 查看哈希值)

上传时间 源代码

构建分发

pypiserver-2.2.0-py2.py3-none-any.whl (93.5 kB 查看哈希值)

上传时间 Python 2 Python 3

由以下支持