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 在 构建工具 中
每月 93 次下载
330KB
7K SLoC
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
以创建新项目文件夹。init
从requirements.txt
或Pipfile
导入数据;new
创建一个包含基本文件的文件夹。 - 运行
pyflow install requests
等命令来安装包。或者,直接编辑pyproject.toml
。 - 运行
pyflow
或pyflow myfile.py
来运行Python。
为快速脚本快速启动
- 在脚本中添加一行
__requires__ = ['numpy', 'requests']
,其中numpy
和requests
是依赖项。运行pyflow script myscript.py
,其中myscript.py
是您的脚本名称。这将为此脚本设置一个隔离环境,并按需安装依赖项。这是一种安全的方式运行非项目Python文件,但这些文件有依赖项。
为什么要添加另一个Python管理器?
Pipenv
、Poetry
和Pyenv
解决了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.0
和Dep B。
Dep B需要Dep
A == 0.9
)在许多情况下,Poetry
和Pipenv
将无法解决依赖项。尝试使用从pypi获取的几个随机依赖项;使用《Poetry
》或《Pipenv
》时,有很大可能会遇到这个问题。局限性:这将对某些编译依赖项无效,并尝试使用这种方法打包某些内容将触发错误。
可能最大的哲学区别是Pyflow抽象了环境,而不是期望用户来管理它们。
我的操作系统自带Python,虚拟环境很容易设置。这有什么意义呢?
有些人喜欢虚拟环境的工作流程——它只需要Python自带的一些工具,并且使用很少的控制台命令来创建、激活和设置环境。然而,这可能会很繁琐,取决于工作流程:命令可能很长,取决于虚拟环境和项目的路径,并且每次使用时都需要修改终端的状态,这可能会让你觉得不方便或不优雅。
我认为我们可以做得更好。这对于不熟悉venvs或不知道与系统Python一起工作的风险的新Python用户尤其相关。
Pipenv
通过自动化环境使用并允许可重复的依赖项图来改进工作流程。《Poetry
》通过改进API、速度、依赖项解析以及通过使用项目配置的整合来改进打包和分发过程。《Poetry
》都对它们运行的环镜很敏感,如果不按预期运行,则无法正常工作。
Conda
优雅地解决了这些问题,但维护着从《PyPi
》独立的二进制代码库。如果所有需要的包都在《Conda
》上,这可能是一个最佳的解决方案。如果不是,则需要回退到《Pip
》,这意味着使用两个不同的包管理器。
在构建和部署软件包时,通常使用一组重叠的文件:setup.py
、setup.cfg
、requirements.txt
和MANIFEST.in
。我们使用pyproject.toml
作为构建和发布所需的项目信息的单一来源。
一个完全有偏见的特性表
这些工具具有不同的作用域和用途
名称 | Pip + venv | Pipenv | Poetry | pyenv | pythonloc | Conda | 此 |
---|---|---|---|---|---|---|---|
管理依赖项 | ✓ | ✓ | ✓ | ✓ | ✓ | ||
解析/锁定依赖项 | ✓ | ✓ | ✓ | ✓ | |||
管理 Python 安装 | ✓ | ✓ | ✓ | ||||
Py-environment-agnostic | ✓ | ✓ | ✓ | ||||
包含在 Python 中 | ✓ | ||||||
与项目一起存储依赖项 | ✓ | ✓ | ✓ | ||||
需要更改会话状态 | ✓ | ✓ | |||||
干净的构建/发布流程 | ✓ | ✓ | |||||
支持旧版本的 Python | 使用 virtualenv |
✓ | ✓ | ✓ | ✓ | ✓ | |
为脚本提供隔离环境 | ✓ | ||||||
从 CLI 运行项目函数 | ✓ | ✓ | ✓ |
用法
- 可选地,在您的项目目录中创建一个
pyproject.toml
文件。否则,此文件将自动创建。您可能希望使用pyflow new
创建一个基本的项目文件夹(包含 .gitignore、源目录等),或者使用pyflow init
从requirements.txt
或Pipfile
中获取信息。有关详细信息,请参阅 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.toml
的 tool.poetry 部分解析元数据和依赖项,因此如果您使用该工具,则无需修改格式。
您可以使用类似以下方式在 pyproject.toml
中指定程序各部分的直接入口点
[tool.pyflow.scripts]
name = "module:function"
在这里,您将 name
、function
和 module
替换为您用于调用脚本的名称、您希望运行的函数以及它所在的模块。这与为构建的包指定 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 REPLpyflow main.py
- 运行 Python 文件pyflow ipython
、pyflow 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.txt
和Pipfile
中提取信息。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 test
(https://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/requests
,https://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