py Poetry
version problem
您遇到的错误表明系统尝试使用 Python 3.11 的解释器来运行 pip,但是该解释器不存在。这通常是因为 pip 脚本的 shebang(即文件开头指定解释器的 #! 行)指向了错误的路径。
要解决这个问题,您需要确保 pip 关联到正确的 Python 版本。请按照以下步骤操作:
-
找到
pip的位置: 使用which命令来找到pip的位置:which pip -
编辑
pip脚本: 使用文本编辑器(如nano)来编辑pip脚本:nano $(which pip)或者如果
which pip返回的是/opt/homebrew/bin/pip,您可以直接编辑:nano /opt/homebrew/bin/pip -
更改 shebang 行: 在打开的
pip脚本中,将第一行的 shebang 更改为正确的 Python 3.12 解释器路径。例如:#!/opt/homebrew/opt/python@3.12/bin/python3.12请确保这个路径是您系统中 Python 3.12 实际的安装位置。保存并关闭编辑器。
-
重新链接 Python: 如果您不确定 Python 3.12 的确切路径,或者上述步骤不起作用,尝试重新链接 Python 3.12:
brew unlink python@3.11
brew link python@3.12 --force然后再次检查
pip是否正确关联到 Python 3.12:pip --version -
更新您的 shell 配置: 如果您的
PATH环境变量没有正确设置,您可能需要更新它。编辑您的 shell 配置文件(对于 zsh,通常是.zshrc):nano ~/.zshrc确保您的
PATH包含 Homebrew 的 Python 安装路径:export PATH="/opt/homebrew/bin:$PATH"保存并关闭文件,然后运行
source ~/.zshrc或重新打开终端窗口以应用更改。
如果您在执行这些步骤时遇到任何问题,或者不确定如何进行,请提供更多的信息,以便我能够提供更具体的帮助。
以上方案均不可行
pipx
https://pipx.pypa.io/stable/installation/
poetry
https://python-poetry.org/docs/#installing-with-the-official-installer

如果您收到 command not found: poetry 的消息,这意味着 Poetry 并没有安装在您的系统上。要安装 Poetry,您可以遵循以下步骤:
首先,确保您的系统上安装了 Python 和其包管理工具 pip。然后,您可以使用官方安装脚本来安装 Poetry。以下是在 Unix-like 系统(包括 macOS)上安装 Poetry 的步骤:
curl -sSL https://install.python-poetry.org | python3 -
这个脚本会自动检测您的 Python 版本,并安装适当版本的 Poetry。
安装完成后,您可能需要配置您的 shell,以便 poetry 命令可以被找到。安装脚本通常会自动添加必要的路径到您的 shell 配置文件中(比如 .bashrc, .zshrc, .profile 等)。您可能需要重新启动您的终端或者手动加载配置文件(使用 source ~/.bashrc 或者对应的配置文件)。
如果您使用的是 zsh,并且在默认的配置文件中没有找到 poetry 的路径,您可以手动添加它。通常,Poetry 会被安装到 $HOME/.poetry 目录中。您可以将以下行添加到您的 .zshrc 文件中:
export PATH="$HOME/.poetry/bin:$PATH"
然后,运行以下命令来应用更改:
source ~/.zshrc
之后,您应该能够运行 poetry 命令。您可以通过运行以下命令来验证 Poetry 是否已正确安装:
poetry --version
如果显示了版本号,那么 Poetry 就已经成功安装了。接下来,您可以回到之前的步骤,继续初始化您的项目:
cd ~/Desktop/temp/trade/binance
poetry init
这将引导您通过创建新项目的 pyproject.toml 文件的过程。
每个模块执行后会生成 __pycache__ 文件
是的,当 Python 模块被执行时,通常会在模块所在的目录中创建一个名为 __pycache__ 的子目录。这个目录用于存储编译过的模块字节码文件,这些文件通常具有 .pyc 扩展名。
这些 .pyc 文件是模块源代码的编译版本,它们是为了加快后续加载该模块的速度。当 Python 加载一个模块时,它会首先检查 __pycache__ 目录中是否存在对应的编译版本(字节码),如果存在且源文件没有更改,则直接加载 .pyc 文件,从而避免重新编译源代码,提高加载速度。
每个 .pyc 文件的命名通常包含了 Python 的版本号,以确保字节码与使用的 Python 解释器版本兼容。例如,如果你使用的是 Python 3.8,编译后的文件可能看起来像这样:module_name.cpython-38.pyc。
如果你不希望在你的源代码目录中生成 __pycache__ 目录,你可以通过设置环境变量 PYTHONDONTWRITEBYTECODE 来禁止它。在 Unix-like 系统中,你可以在命令行中设置这个变量:
export PYTHONDONTWRITEBYTECODE=1
在 Windows 系统中,你可以使用:
set PYTHONDONTWRITEBYTECODE=1
或者,你可以在运行 Python 脚本时使用 -B 选项来禁止写入字节码文件:
python -B script.py
请注意,禁用字节码文件的生成可能会导致程序启动时加载模块的速度变慢,因为每次都需要重新编译源代码。
poetry 模块执行
执行 binance 模块的 watch-price 模块
poetry run python -m module_binance.watch-price btcusdt 100 4
更改模块名,模块的引用自动重构
执行 main 模块的 main 函数
poetry run python -B -m main.main
# -B 不生成__pycache__目录文件
执行 module_a 模块的 a 函数
poetry run python -B -m module_a.a
# -B 不生成__pycache__目录文件
执行 module_b 模块的 b 函数
poetry run python -B -m module_b.b
# -B 不生成__pycache__目录文件
poetry 模块引入
引入整个模块
是的,您可以引入整个模块而不仅仅是模块中的特定函数或类。当您导入整个模块时,您可以使用模块名作为名称空间来访问模块中定义的所有公共属性和函数。
例如,如果您想要导入整个 module_b 和 module_c,而不是它们各自的 say_hello 函数,您可以这样做:
module_a/a.py:
import module_b.b
import module_c.c
def main():
module_b.b.say_hello()
module_c.c.say_hello()
if __name__ == "__main__":
main()
在这个示例中,我们使用 import module_b.b 和 import module_c.c 语句来导入整个模块。然后我们使用 module_b.b.say_hello() 和 module_c.c.say_hello() 来调用各自模块中的 say_hello 函数。
这种导入整个模块的方法有助于保持命名空间的清晰,因为您必须使用模块名来访问函数,这样可以避免函数名之间的冲突。此外,如果模块中还有其他函数或变量,您也可以使用相同的模块名前缀来访问它们。
如果模块名过长或者您想用一个更简短的别名来引用它,您可以使用 as 关键字为模块指定一个别名:
import module_b.b as mod_b
import module_c.c as mod_c
def main():
mod_b.say_hello()
mod_c.say_hello()
if __name__ == "__main__":
main()
在这个例子中,mod_b 和 mod_c 分别作为 module_b.b 和 module_c.c 的别名,您可以通过这些别名来访问模块中的内容。
如果 B 模块下有多个文件呢,该如何引入
如果模块 B 下有多个文件(即子模块),您可以选择单独引入每个子模块,或者引入整个 B 模块(如果它包含一个__init__.py文件来将它定义为一个包)。下面是一些示例说明如何进行操作。
假设模块 B 的目录结构如下:
module_b/
__init__.py
sub_module1.py
sub_module2.py
引入子模块
如果您只想引入sub_module1和sub_module2,可以这样做:
from module_b import sub_module1
from module_b import sub_module2
sub_module1.some_function()
sub_module2.another_function()
引入整个模块 B
如果您想引入整个模块 B,并通过它来访问子模块,您需要在__init__.py文件中导入这些子模块,然后您可以这样引入整个模块 B:
module_b/__init__.py:
from . import sub_module1
from . import sub_module2
然后在另一个文件中:
import module_b
module_b.sub_module1.some_function()
module_b.sub_module2.another_function()
或者,使用别名:
import module_b as mb
mb.sub_module1.some_function()
mb.sub_module2.another_function()
使用__all__在__init__.py中指定导出的子模块
在__init__.py文件中,您可以定义一个名为__all__的列表,用来指定当使用from module_b import *时应该导入哪些子模块:
module_b/__init__.py:
__all__ = ['sub_module1', 'sub_module2']
然后您可以这样引入所有指定的子模块:
from module_b import *
sub_module1.some_function()
sub_module2.another_function()
请注意,通常不推荐使用import *,因为它可能导致命名空间污染,而且不清楚代码中使用的名称来自哪里。明确地指定要导入的子模块通常是一个更好的做法。
每个文件都是一个模块?
在 Python 中,每个独立的.py文件都被视为一个模块。模块是 Python 组织和重用代码的基本单位。当您创建一个新的.py文件并在其中编写函数、类或变量时,您实际上是在创建一个可以被其他 Python 脚本导入和使用的模块。
例如,如果您有一个名为my_module.py的文件,它包含以下内容:
# my_module.py
def my_function():
print("Hello from my_function!")
class MyClass:
def my_method(self):
print("Hello from my_method!")
这个文件my_module.py本身就是一个模块,名为my_module。您可以在其他 Python 文件中导入这个模块并使用它的内容,如下所示:
# another_file.py
import my_module
my_module.my_function() # 调用函数
instance = my_module.MyClass() # 创建类的实例
instance.my_method() # 调用方法
模块可以包含可执行的代码,以及函数定义、类定义和其他对象。当模块被导入时,模块中的顶级代码将被执行一次,定义的函数和类将变得可用,但如果有可执行的语句,它们也会在导入时执行。
模块还可以组织成包。包是包含多个模块的目录,它有一个特殊的文件__init__.py(可以是空的),这个文件标志着该目录是一个 Python 包。这允许您将相关的模块组织在一起,形成一个层次结构,便于管理和导入。
poetry 与 fastapi 一起使用
base
Poetry 是一个现代的 Python 依赖管理和打包工具,它允许你声明项目所依赖的库,并管理这些库的版本。FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,它基于标准 Python 类型提示。
要将 Poetry 与 FastAPI 一起使用,你需要按照以下步骤操作:
-
安装 Poetry:如果你还没有安装 Poetry,可以从官方网站获取安装指南:https://python-poetry.org/docs/#installation。
-
创建一个新的 Poetry 项目:在你希望创建新项目的目录中打开终端,然后运行以下命令:
poetry new my-fastapi-project这将创建一个名为
my-fastapi-project的新目录,其中包含一些基础文件和目录结构。 -
添加 FastAPI 作为依赖:切换到项目目录,并使用 Poetry 添加 FastAPI:
cd my-fastapi-project
poetry add fastapi这将自动将 FastAPI 添加到你的
pyproject.toml文件中,并安装 FastAPI。 -
添加 ASGI 服务器:FastAPI 是一个 ASGI 框架,因此你需要一个 ASGI 服务器来运行它。常用的 ASGI 服务器有 Uvicorn 和 Hypercorn。以下是如何添加 Uvicorn:
poetry add uvicorn -
创建你的 FastAPI 应用:在项目目录中创建一个 Python 文件来编写你的 FastAPI 应用,例如
main.py:# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"} -
运行你的 FastAPI 应用:使用 Uvicorn 运行你的应用。Poetry 允许你通过它的
run命令来运行与你的项目相关的命令:poetry run uvicorn main:app --reload这里的
main:app表示 Uvicorn 应该在main.py文件中寻找名为app的 ASGI 应用实例。--reload参数使服务器在代码更改时自动重启。
通过以上步骤,你就可以使用 Poetry 管理你的 FastAPI 项目依赖,并运行你的 FastAPI 应用了。Poetry 的好处在于,它为你的项目创建了一个隔离的虚拟环境,这意味着你安装的依赖不会影响到其他 Python 项目或全局 Python 环境。
项目参考
https://github.com/tiangolo/full-stack-fastapi-template/blob/master/backend/pyproject.toml
Poetry 依赖组是什么意思
在 Poetry 中,依赖组是一种组织和管理项目依赖的方式,允许你为不同的使用场景定义不同的依赖集合。默认情况下,Poetry 有两个主要的依赖组:
-
dependencies:这是项目的主要依赖组,包含了项目运行时所必需的所有库。这些依赖会被安装在任何情况下,无论是在开发还是在生产环境中。 -
dev-dependencies:这个组包含了项目开发时所需的依赖,例如单元测试库、代码格式化工具或文档生成工具。这些依赖仅在开发环境中安装,不会在部署到生产环境时安装。
Poetry 1.2 版本引入了自定义依赖组的概念,这意味着你可以创建额外的依赖组来满足特定需求。例如,你可能想要一个只在进行性能测试时使用的依赖组,或者一个专门用于构建 Docker 容器的依赖组。
在 pyproject.toml 文件中定义自定义依赖组的例子如下:
[tool.poetry.dependencies]
python = "^3.8"
fastapi = "^0.65.0"
[tool.poetry.dev-dependencies]
pytest = "^6.2.4"
[tool.poetry.group.performance.dependencies]
locust = "^1.6.0"
[tool.poetry.group.docker.dependencies]
gunicorn = "^20.1.0"
在上面的例子中,除了默认的 dependencies 和 dev-dependencies 组外,我们还创建了 performance 和 docker 两个自定义依赖组。每个组都有它自己的依赖。
要安装特定依赖组的依赖,你可以使用以下命令:
poetry install --only main,performance
这将只安装 dependencies 和 performance 组的依赖。
自定义依赖组提供了更大的灵活性,使得项目的依赖管理更加清晰和有针对性。