Python 打包未运行,被视为模块

python packaging not running, treated like a module

提问人:user3227671 提问时间:11/3/2023 最后编辑:user3227671 更新时间:11/3/2023 访问量:41

问:

我正在尝试在 Windows 10 上的 python 3.11.6 中创建一个包,该包具有访问各种代码模块的相对路径,首先,我认为基本打包会起作用,即只需放置一个空的顶级 init.py,并为每个目录添加一个类似的文件。这对我不起作用。

my_project/
   __init__.py
   src_1/
      __init__.py
      first.py
   src_2/
      __init__.py
      second.py

如果我尝试从顶级目录执行 second.py,则会出现导入错误。 如果我使用所有 3 个目录设置 PYTHONPATH,我 second.py 成功访问 first.py

我不想使用环境变量,因为项目几乎肯定会移动,而且我不想为每个安装配置它们。顺便说一句,我认为这就是打包的作用,首先运行顶级 init.py,较低级别的任何代码都应该能够从同级目录导入?

在我尝试实现相对路径时,顶级 init.py 包含:

import os
import sys

# Get the current directory where this __init__.py file is located
current_directory = os.path.dirname(os.path.abspath(__file__))

# Add project-specific directories to the Python path
project_path = current_directory
src_1_path = os.path.join(current_directory, 'src_1')
src_2_path = os.path.join(current_directory, 'src_2')

sys.path.insert(0, project_path)
sys.path.insert(0, src_1_path)
sys.path.insert(0, src_2_path)

其他 2 个 init.py 文件为空。

first.py 包含:

import sys

def print_sys_path():
    print(sys.path)

second.py 包含:

import first

if __name__ == "__main__":
    # bar will be invoked if this module is being run directly, but not via import!
    first.print_sys_path()

当我运行它时,我收到以下错误:

D:\my_project>py src_2\second.py 回溯(最近一次调用最后一次): 文件“D:\my_project\src_2\second.py”,第 1 行,在 首先导入 ModuleNotFoundError:没有名为“first”的模块

我最终的项目将有一个类似的结构,我只是想为它找出与路径无关的打包。

我可能一开始走错了方向。我计划在我交付的项目中采用以下结构:

my_project/
   __init__.py
   my_database/
      __init__.py
      database.py
   my_gui/
      __init__.py
      gui.py
   my_process/
      __init__.py
      process.py

..并希望最终使用 pyinstaller 将其打包为 2 个单独的可执行文件,gui.exe 和 processor.exe。

是的,我是 Python、打包等的新手,所以请温柔一点。我已经阅读了文档。我找不到任何与我的问题相关的内容,这些内容实际上可以解决问题。

感谢您的时间和精力!

python relative-path

评论


答:

0赞 KhodeNima 11/3/2023 #1

您好先生/女士。


不幸的是,我们的男孩蟒蛇使用了最烦人的打包系统之一, 太烦人了,我从来没有见过初学者刚开始包的概念 而不是陷入这个问题。


进口:


不幸的是,Python 导入系统无法以这种特定方式找到文件,这意味着当您尝试导入 python 时,它会在其主包文件夹中搜索该特定文件(就像导入任何类型的库一样,例如 .x .env、pathlib、sys、ETC),即使您将其添加到您的 python 路径。( 这称为绝对导入。了解相对导入和绝对导入之间的区别会很有帮助。first

但是,您可以使用以下命令导入文件的内容:first


import ..src_1.first

在此相对导入中,语法是 GOING BACK 在包目录中。..


概念


即使您对文件使用这种类型的导入,python 仍然会引发相同的错误。__init__.py

这是因为包的文件不能直接运行,它们不能运行。 在这种情况下,您不应该运行其中一个文件,您应该运行整个文件夹。

python3 -m your_project

打包中文件的概念说来话长,你可以在这里了解更多。__main__.py

长话短说,当你运行整个项目文件夹时,python 会查看包以查找文件。此文件必须位于文件夹层次结构的顶部:__main__.py


your_project/
    __init__.py
    __main__.py

    src_1/
        first.py
        __init__.py

    src_2/
        second.py
        __init__.py

这也意味着 和 文件可以有相对导入,但文件不应该回到目录中,如果你想导入任何其他文件夹,你应该使用它们的绝对路径。second.pyfirst.py__main__.py


执行子包:

不过,如果您想运行子包或以不同的方式处理两个包,尽管它们相互绑定,您可以在此处查找。


建议

如非必要,请勿使用相关进口和包装

python的禅宗:如果实现很难解释,那就不是一个好主意。

尝试使用默认打包系统,并将主文件保持在顶层,避免使用复杂的导入模式。

评论

0赞 user3227671 11/3/2023
感谢您花时间回答这个问题,并付出了明显的努力!显然,你对我最初的努力没有奏效并不感到惊讶,现在,我也不感到惊讶!我的基本要求是最终得到 2 个使用相同数据库的可执行文件,但事后看来,该数据库功能不会在 2 个进程之间共享。简单地说,一个进程将使用某些特定函数写入数据库,而 GUI 进程将读取并显示第一个进程写入的数据。因此,我计划将数据库分成两个单独的文件,gui_db 和 process_db。再次感谢!
0赞 KhodeNima 11/3/2023
@user3227671 我认为您正在寻找与此类似的实现:NyvoHabit 项目