21 个版本

0.3.1 2021 年 7 月 2 日
0.2.9 2020 年 11 月 21 日
0.2.7 2020 年 6 月 3 日
0.2.5 2020 年 3 月 6 日
0.2.2 2019 年 11 月 24 日

139构建工具

Download history 8/week @ 2024-03-29

每月 93 次下载

MIT 许可证

330KB
7K SLoC

Build Status

Pyflow

简单比复杂好 - Python 的禅意

Pyflow 简化了 Python 项目的文件操作。它是一个易于使用的 CLI 应用程序,具有最小化的 API。永远不用担心没有正确的 Python 或依赖项版本。

示例用法,包括设置项目和切换 Python 版本: 演示

如果你的项目已经配置好了,你需要做的唯一命令就是 pyflow,或者 pyflow myscript.py;设置 Python 和其依赖项是自动的。

目标:使使用和发布 Python 项目尽可能简单。使用依赖项时,不需要积极管理 Python 环境。我们试图解决 Python 工作流程中的每个障碍,使其与语言本身一样优雅。

使用 Pyflow,您不需要安装 Python 或其他任何工具。

它在独立环境中运行脚本,无需配置,并直接从 CLI 运行项目功能。

它实现了 PEP 582 — Python 本地包目录PEP 518 (pyproject.toml)

安装

  • Windows - 下载并运行 此安装程序。或者,如果您已安装 Scoop,请运行 scoop install pyflow

  • Ubuntu,或使用 Snap 的其他操作系统 - 运行 snap install pyflow --classic

  • 没有 Snap 的 Ubuntu 或 Debian - 下载并运行 此 deb

  • Fedora、CentOs、RedHat或较旧的SUSE版本 - 下载并运行此rpm包

  • 不同的Linux发行版 - 下载此独立二进制文件并将其放置在PATH可访问的位置。例如,/usr/bin

  • Mac - 运行brew install pyflow

  • 使用Pip - 运行pip install pyflow。使用此方法安装的Linux版本比上述方法大得多,并且目前不支持Mac。此方法可能不适用于Red Hat、CentOs或Fedora。

  • 如果您已安装Rust - 运行cargo install pyflow

快速入门

  • (可选) 在现有项目文件夹中运行pyflow init,或运行pyflow new projname以创建新项目文件夹。initrequirements.txtPipfile导入数据;new创建一个包含基本文件的文件夹。
  • 运行pyflow install requests等命令来安装包。或者,直接编辑pyproject.toml
  • 运行pyflowpyflow myfile.py来运行Python。

为快速脚本快速启动

  • 在脚本中添加一行__requires__ = ['numpy', 'requests'],其中numpyrequests是依赖项。运行pyflow script myscript.py,其中myscript.py是您的脚本名称。这将为此脚本设置一个隔离环境,并按需安装依赖项。这是一种安全的方式运行非项目Python文件,但这些文件有依赖项。

为什么要添加另一个Python管理器?

PipenvPoetryPyenv解决了Pyflow部分的原因,但可能会在新用户安装和使用时遇到障碍。以下是一些不同之处的原因

  • 无论您的系统和Python安装如何配置,它都能保持一致的行为。

  • 它自动管理Python安装和环境。您在pyproject.toml中指定Python版本(如果省略,则询问),并确保使用该版本。如果该版本未安装,Pyflow将下载二进制文件并使用它。如果找到了多个该版本的安装,它将询问使用哪个。使用Pyenv安装Python时,只有当您的系统以某种方式配置时才适用:我认为期望用户计算机编译Python是不合理的。

  • 由于不使用Python进行安装或运行,因此它保持环境无关性。这可以使设置和使用尽可能简单和自由选择。Python基于的CLI工具在从pip安装时通常无法正确运行,这是由于PATH或用户目录未按预期配置。

  • 由于使用缓存的依赖数据库,其依赖项解析和锁定速度更快,而不是下载和检查每个包,或依赖于pypi仓库上不完整的数据。Pipenv的解析在弱互联网连接上可能非常慢。

  • 它将依赖项保存在项目目录中的__pypackages__中。这很微妙,但强化了没有隐藏状态的想法。

  • 它将始终使用指定的Python版本。这是在《Poetry》中的一个显著限制;Poetry可能会选择错误的安装(例如Python2而不是Python3),并且没有明显的方法来更改它。Poetry允许项目指定版本,但既不选择,也不提供选择正确版本的方法。如果选择了错误的版本,它将安装错误的虚拟环境,并产生令人困惑的错误信息。可以通过使用《Pyenv》来解决这个问题,但这并不是官方文档化的解决方案,并且会增加工作流程的摩擦。它可能会让新用户感到困惑,因为它在默认情况下出现在流行的Linux发行版(如Ubuntu)上。此外,《Pyenv》的文档很令人困惑:不清楚如何安装它,它与哪些操作系统兼容,或者需要哪些额外的依赖项。

  • 可以安装依赖项的多个版本,从而可以解决冲突的子依赖项。例如:您的软件包需要Dep A >= 1.0Dep BDep B需要Dep A == 0.9)在许多情况下,PoetryPipenv将无法解决依赖项。尝试使用从pypi获取的几个随机依赖项;使用《Poetry》或《Pipenv》时,有很大可能会遇到这个问题。局限性:这将对某些编译依赖项无效,并尝试使用这种方法打包某些内容将触发错误。

可能最大的哲学区别是Pyflow抽象了环境,而不是期望用户来管理它们。

我的操作系统自带Python,虚拟环境很容易设置。这有什么意义呢?

希望我们不会用一个问题来取代另一个问题

有些人喜欢虚拟环境的工作流程——它只需要Python自带的一些工具,并且使用很少的控制台命令来创建、激活和设置环境。然而,这可能会很繁琐,取决于工作流程:命令可能很长,取决于虚拟环境和项目的路径,并且每次使用时都需要修改终端的状态,这可能会让你觉得不方便或不优雅。

我认为我们可以做得更好。这对于不熟悉venvs或不知道与系统Python一起工作的风险的新Python用户尤其相关。

Pipenv通过自动化环境使用并允许可重复的依赖项图来改进工作流程。《Poetry》通过改进API、速度、依赖项解析以及通过使用项目配置的整合来改进打包和分发过程。《Poetry》都对它们运行的环镜很敏感,如果不按预期运行,则无法正常工作。

Conda优雅地解决了这些问题,但维护着从《PyPi》独立的二进制代码库。如果所有需要的包都在《Conda》上,这可能是一个最佳的解决方案。如果不是,则需要回退到《Pip》,这意味着使用两个不同的包管理器。

在构建和部署软件包时,通常使用一组重叠的文件:setup.pysetup.cfgrequirements.txtMANIFEST.in。我们使用pyproject.toml作为构建和发布所需的项目信息的单一来源。

一个完全有偏见的特性表

这些工具具有不同的作用域和用途

名称 Pip + venv Pipenv Poetry pyenv pythonloc Conda
管理依赖项
解析/锁定依赖项
管理 Python 安装
Py-environment-agnostic
包含在 Python 中
与项目一起存储依赖项
需要更改会话状态
干净的构建/发布流程
支持旧版本的 Python 使用 virtualenv
为脚本提供隔离环境
从 CLI 运行项目函数

用法

  • 可选地,在您的项目目录中创建一个 pyproject.toml 文件。否则,此文件将自动创建。您可能希望使用 pyflow new 创建一个基本的项目文件夹(包含 .gitignore、源目录等),或者使用 pyflow initrequirements.txtPipfile 中获取信息。有关详细信息,请参阅 PEP 518

示例内容

[tool.pyflow]
py_version = "3.7"
name = "runcible"
version = "0.3.1"
authors = ["John Hackworth <[email protected]>"]

[tool.pyflow.dependencies]
numpy = "^1.16.4"
diffeqpy = "1.1.0"

用于元数据的 [tool.pyflow] 部分。除非构建和分发包,否则其中唯一必需的项是 py_version[tool.pyflow.dependencies] 部分包含所有依赖项,类似于 requirements.txt。您可以在 [tool.pyflow.dev-dependencies] 部分中指定开发依赖项。这些依赖项将不会打包或发布,但会本地安装。您可以使用带有 --dev 标志的 CLI 安装这些依赖项。例如:pyflow install black --dev

您可以指定 extra 依赖项,这些依赖项仅在传递显式标志到 pyflow install 时安装,或者在包含适当标志的另一个项目中安装。即需要此依赖项的包可以启用 pip install -e 等。

[tool.pyflow.extras]
test = ["pytest", "nose"]
secure = ["crypto"]

如果您想使用额外功能安装依赖项,请使用如下语法

[tool.pyflow.dependencies]
ipython = { version = "^7.7.0", extras = ["qtconsole"] }

要从本地路径而不是 pypi 安装,请使用如下语法

[tool.pyflow.dependencies]
# packagename = { path = "path-to-package"}
numpy = { path = "../numpy" }

要从 git 仓库安装,请使用如下语法

[tool.pyflow.dependencies]
saturn = { git = "https://github.com/david-oconnor/saturn.git" }  # The trailing `.git` here is optional.

git 依赖项目前处于实验阶段。如果您遇到问题,请提交问题。

如果包名称中包含 .,请将名称用引号括起来。

有关如何以此 Cargo.toml-受灵感的 semver 格式指定依赖项的详细信息,请参阅 本指南

我们还尝试从 pyproject.tomltool.poetry 部分解析元数据和依赖项,因此如果您使用该工具,则无需修改格式。

您可以使用类似以下方式在 pyproject.toml 中指定程序各部分的直接入口点

[tool.pyflow.scripts]
name = "module:function"

在这里,您将 namefunctionmodule 替换为您用于调用脚本的名称、您希望运行的函数以及它所在的模块。这与为构建的包指定 setup.py 中的脚本类似。主要区别在于这里指定的函数可以在任何时间运行,而无需构建包。使用 pyflow name 来运行。

如果您在一个使用该工具的包上运行 pyflow package,其结果将类似于使用该包的人使用的正常脚本入口点,无论他们是否使用此工具。

您可以做什么

管理依赖关系

  • pyflow install - 安装 pyproject.toml 中的所有包,并移除未(递归地)指定的包。如果尚未为 pyproject.toml 中指定的版本设置环境,则设置一个。请注意,此命令不是同步依赖项所必需的;任何相关的 pyflow 命令都将自动执行此操作。
  • pyflow install requests - 如果您在 install 后指定了一个或多个包,则这些包将被添加到 pyproject.toml 并安装。您可以使用 --dev 标志安装开发依赖项。例如:pyflow install black --dev
  • pyflow install numpy==1.16.4 matplotlib>=3.1 - 具有多个依赖项和指定版本的示例
  • pyflow uninstall requests - 删除一个或多个依赖项

在环境中运行 REPL 和 Python 文件

  • pyflow - 运行 Python REPL
  • pyflow main.py - 运行 Python 文件
  • pyflow ipythonpyflow black 等 - 运行 CLI 工具,如 ipython,或项目函数。对于前者,它必须由依赖项安装;对于后者,它指定在 [tool.pyflow]scripts
  • pyflow script myscript.py - 运行一个一次性脚本,位于项目目录之外,具有按文件管理的包

构建和发布

  • pyflow package - 打包用于分发(内部使用 setuptools,并构建源和 wheel。)
  • pyflow package --extras "test all" - 具有额外功能启用的分发包,如 pyproject.toml 中定义的
  • pyflow publish - 上传到 PyPi(在 pyproject.toml 中指定了仓库。内部使用 Twine。)

杂项

  • pyflow list - 显示所有已安装的包和控制台脚本
  • pyflow new projname - 创建包含项目基本内容的目录:readme、pyproject.toml、.gitignore 和代码目录
  • pyflow init - 在现有项目目录中创建 pyproject.toml 文件。根据需要从 requirements.txtPipfile 中提取信息。
  • pyflow reset - 删除环境,并卸载所有包
  • pyflow clear - 清除缓存,包括下载的依赖项、Python 安装或脚本环境;它将询问您要清除哪些。
  • pyflow -V - 获取此工具的当前版本
  • pyflow help 获取帮助,包括可用命令列表

安装和锁定的工作方式

运行 pyflow install 将项目的已安装依赖项与 pyproject.toml 中指定的依赖项同步。它生成 pyflow.lock 文件,在后续运行中,只要它继续满足 pyproject.toml 中指定的约束,就会保持每个软件包的固定版本。通过 CLI 添加包名,例如 pyflow install matplotlib,简单地将该要求添加到继续操作之前。不要直接编辑 pyflow.lock 文件。

pyproject.toml 中列出的每个依赖项都会在 pyflow.lock 中检查兼容匹配。如果锁文件中的某个内容满足约束,则我们将同步的版本将与锁文件中列出的版本匹配。如果不满足,则会在锁文件中添加一个新条目,包含由 pyproject.toml 允许的最高版本。一旦完成,就会安装和删除软件包,以精确满足更新的锁文件中列出的那些。

此工具从 pypi 下载并解压缩 wheels,如果没有可用的话,会从源代码构建 wheels。它使用 SHA256 验证下载文件的完整性,并将确切使用的版本存储在锁文件中。

当从 pyproject.toml 中移除依赖项时,它及其子依赖项(如果它们不是由其他软件包要求的)将从 __pypackages__ 文件夹中删除。

依赖项的解析方式

使用来自 PyPi Warehouse(可用版本和哈希信息)和 pydeps 数据库的信息确定依赖项的兼容版本。我们使用专门为该项目构建的 pydeps,因为 pypi 上存储的依赖项信息不一致。使用缓存的数据库构建依赖项图。我们尝试使用每个软件包的最新兼容版本。

如果所有软件包只指定一次,或者以相同的最新兼容版本多次指定,则解析完成,准备安装和同步。

如果某个软件包包含多于一次,并且具有不同的最新兼容版本,但其中一个最新兼容版本与所有要求兼容,则安装该版本。如果不兼容,则搜索所有版本以找到兼容版本。

如果仍然无法找到满足所有要求的软件包版本,则按需安装多个版本,将它们存储在单独的目录中,并根据需要修改父目录的导入。

注意,在上述情况之外,可能还可以解析依赖项,而不是安装多个版本。例如,我们可以尝试不同的顶级软件包组合,检查解析,然后按需在层次结构中修改子软件包。我们不这样做,因为它很慢,没有成功保证,并且涉及安装软件包的旧版本。

尚未实现

  • 安装全局 CLI 工具
  • 锁文件缺少一些信息,如哈希值
  • 通过 CLI 添加具有特定版本约束或额外内容的依赖项
  • 直接从本地 wheel 安装软件包。同时,您可以使用解压缩 wheels 的 path 依赖项。
  • 处理使用 importlib 或动态导入的依赖项的多个已安装版本
  • 在 Mac 上安装 Python

构建并将您的项目上传到 PyPi

为了构建和发布您的项目,需要在 pyproject.toml 中提供额外的信息,该信息类似于 setup.py 中的内容。示例

[tool.pyflow]
name = "everythingkiller"
py_version = "3.6"
version = "0.3.1"
authors = ["Fraa Erasmas <[email protected]>"]
description = "Small, but packs a punch!"
homepage = "https://everything.math"
repository = "https://github.com/raz/everythingkiller"
license = "MIT"
keywords = ["nanotech", "weapons"]
classifiers = [
    "Topic :: System :: Hardware",
    "Topic :: Scientific/Engineering :: Human Machine Interfaces",
]
python_requires = ">=3.6"
# If not included, will default to `test.pypi.org`
package_url = "https://upload.pypi.org/legacy/"


[tool.pyflow.scripts]
# name = "module:function"
activate = "jeejah:activate"


[tool.pyflow.dependencies]
numpy = "^1.16.4"
manimlib = "0.3.1"
ipython = {version = "^7.7.0", extras=["qtconsole"]}


[tool.pyflow.dev-dependencies]
black = "^18.0"

package_url 用于确定要上传到哪个软件包存储库。如果省略,则使用 Pypi testhttps://test.pypi.org/legacy/)。

您可以在 [tool.pyflow] 中指定的其他项目。

  • readme:readme 文件名,如果文件名不是 README.md,请使用此选项。
  • build:一个 Python 脚本,在运行 pyflow package 时执行构建非 Python 扩展。

从源代码构建

如果您想从源代码构建,请下载并安装 Rust,克隆仓库,然后在仓库目录下运行 cargo build --release

即在 Linux 或 Mac 上

curl https://sh.rustup.rs -sSf | sh
git clone https://github.com/david-oconnor/pyflow.git
cd pyflow
cargo build --release

更新

  • 如果通过 Scoop 安装,请运行 scoop update pyflow
  • 如果通过 Snap 安装,请运行 snap refresh pyflow
  • 如果通过 Cargo 安装,请运行 cargo install pyflow --force
  • 如果通过 Pip 安装,请运行 pip install --upgrade pyflow
  • 如果使用安装程序或 deb,请运行新版本的安装程序或 deb。如果手动调用二进制文件,请替换它。

卸载

  • 如果通过 Scoop 安装,请运行 scoop uninstall pyflow
  • 如果通过 Snap 安装,请运行 snap remove pyflow
  • 如果通过 Cargo 安装,请运行 cargo uninstall pyflow
  • 如果通过 Pip 安装,请运行 pip uninstall pyflow
  • 如果通过 Windows 安装程序安装,请再次运行安装程序并选择请求时删除,或者使用 Apps & features
  • 如果通过 deb 安装,请使用 Software Center
  • 如果手动调用二进制文件,请删除它。

贡献

如果您注意到意外的行为或缺少的功能,请发布一个问题,或提交一个 PR。如果您看到意外的行为,这可能是错误!发布一个列出未正确安装的依赖项的问题。

为什么不要使用这个

  • 它为已经复杂的领域添加了另一个工具。
  • 这里的大部分功能已经由表上的一系列现有软件包提供。
  • 由于是用不同的语言编写的,因此贡献者领域预计会很小。
  • 像 Pipenv 和 Poetry 这样的依赖项管理器对于许多情况来说已经足够好,有专门的开发团队,并且拥有庞大的用户群体。
  • Conda 尤其擅长处理许多此类功能。

依赖项缓存仓库

  • Github 示例 API 调用:https://pydeps.herokuapp.com/requestshttps://pydeps.herokuapp.com/requests/2.21.0。这拉取了 requests 软件包的所有顶级依赖项,以及版本 2.21.0 的依赖项。还有一个 POST API 用于拉取指定版本的详细信息。对于第一个运行的软件包/版本组合,可能较慢。随后的调用,由任何人,应该很快。这是由于需要在服务器上下载和安装每个软件包以正确确定依赖项,因为 pypi warehouse 上的信息不可靠。

Python 二进制源代码

仓库二进制文件是从

  • Windows: Python官方Visual Studio包,由Steve Dower提供。
  • 较新的Linux发行版:基于Ubuntu 18.04,使用标准流程构建。
  • 较旧的Linux发行版:基于CentOS 7,使用标准流程构建。

注意事项

  • 请确保__pypackages__已添加到您的.gitignore文件中。
  • 您可能需要设置IDE以在__pypackages__中查找包。如果使用PyCharm: 设置项目项目解释器显示所有... → (选择解释器,即 Linux/Mac 上的 (projname)/__pypackages__/3.x/.venv/bin/python 或 Windows 上的 (projname)/__pypackages__/3.x/Scripts/python) → 点击弹出窗口底部的文件夹树图标 → 点击新弹出窗口底部的 + 图标 → 导航到并选择 (projname)/__pypackages__/3.x/lib
  • 如果使用VsCode: 设置 → 搜索 python extra paths在设置中编辑in settings.json → 添加或修改以下行: "python.autoComplete.extraPaths": ["(projname)/__pypackages__/3.7/lib"]

参考

依赖

~33–47MB
~1M SLoC