从python中的同级文件夹导入函数会产生奇怪的错误

2024-04-25 08:47:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个脚本'zigbot.py',这是工作,但我重组dockerize,现在我质疑我的能力,代码在所有。我要做的是有一个telegrambot容器、一个“web”容器(FLASK)和一个nginx容器

在zigbot.py旁边,我有一个文件夹-“bot”,里面有我的许多脚本和函数。在尝试from bot.somescript import a_function时,我得到了一个又一个错误

项目结构

zigbot
    bot
        bot
            __init__.py
            conversations.py
            ct.py
            Docerfile
            funcs.py
            pricedata.py
            requirements.txt
            util.py
        zigbot.py
    nginx
        somestuff
    web
        app
            migrations
            templates
            __init__.py
            config.py
            forms.py
            functions.py
            models.py
            routes.py
            signals.py
        __init__.py
        Dockerfile
        requirements.txt
        zigweb.py

当运行下面的代码时,我得到一系列奇怪的错误-下面列出的一个显示importorror-它在funcs中找不到'onboard',但它肯定在那里。在重组之前,这是可行的。如果我在列表中的每个函数上注释掉'onboard'它就会出错

from bot.conversations import key_conversation
from bot.crypto_functions import satoshi_to_btc
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
    onboarded_message, blank_signal_message, send_signal_format, get_or_create_user, signal_detected_keyboard, log_me
Traceback (most recent call last):
  File "zigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
  File "ZigBot\bot\bot\funcs.py", line 2, in <module>
    from zigbot.web.app import db, app
  File "ZigBot\bot\zigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
ImportError: cannot import name 'onboard'

所以我尝试为(相对?)导入添加一个.bot.conversation,但这会产生一个更奇怪的错误。我在下面列出了代码、错误,然后是我试图导入的函数:

from .bot.conversations import key_conversation
from .bot.crypto_functions import satoshi_to_btc
from .bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
    onboarded_message, blank_signal_message, send_signal_format, get_or_create_user, signal_detected_keyboard, log_me
from ..web.app import db
from ..web.app.models import User, Signal
Traceback (most recent call last):
  File "zigbot.py", line 13, in <module>
    from .bot.conversations import key_conversation
ModuleNotFoundError: No module named '__main__.bot'; '__main__' is not a package

对话.py

# Initialise conversationHandler states
def key_conversation(cancel):
    # Define keyboards
    keyboard = [
        [InlineKeyboardButton('Previous', callback_data='onboard:key'),
         InlineKeyboardButton('Next', callback_data='onboard:alldone')]]
    conversation_keyboard = InlineKeyboardMarkup(keyboard)

最后,我想我离问题越来越近了,我回到了我认为应该进口的方式。从bot.funcs导入x,y,y。。。我在funcs.py中查看,它是如何从我的Flask web应用程序导入一些其他代码的,但它不喜欢它

职能部门

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from web.app import db, app
from web.app.models import User
Traceback (most recent call last):
  File "zigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
  File "ZigBot\bot\bot\funcs.py", line 2, in <module>
    from web.app import db, app
ModuleNotFoundError: No module named 'web'

因此,我将导入更改为向上一级,因为web是bot之上的两级,其中包含我要导入的脚本。所以zigbot>bot>bot>funcs.py试图从zigbot>web>app>导入

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from ..web.app import db, app
from ..web.app.models import User
import telegram
Traceback (most recent call last):
  File "zigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
  File "\ZigBot\bot\bot\funcs.py", line 2, in <module>
    from ..web.app import db, app
ValueError: attempted relative import beyond top-level package

这显然也不管用。考虑到我拥有botweb的结构,我该如何让它工作?我甚至试着从第二个“bot”文件夹中取出脚本,但我也遇到了同样的问题。最后,我的最奇怪的错误可能提供了我做错了什么的线索,如果我将funcs.py上的导入更改为向上一级,而不是向上两级,我会得到一个更奇怪的回溯

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from .web.app import db, app
from .web.app.models import User
import telegram
Traceback (most recent call last):
  File "zigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
  File "C:\Users\phill\PycharmProjects\ZigBot\bot\bot\funcs.py", line 2, in <module>
    from .web.app import db, app
ModuleNotFoundError: No module named 'bot.web'

为了清楚起见,我从回溯中删除了一些'C:\Users\phill',然后才意识到删除它是毫无意义的


Tags: infrompyimportwebappnewbot
2条回答

我认为,如果您有跨边界的库依赖关系,那么拆分中就有一个基本缺陷。假设您的web容器中没有导入bot模块,我建议将共享代码中断为名为weblib的模块或其他模块(与bot-、nginx-和web-文件夹一起)

但是,您仍然不应该尝试跨可能的容器边界导入,因此只需确保weblib位于您的路径中,或者安装在您的虚拟环境中,或者以您希望的方式处理它。基本上,botweb应该在不同的环境中运行,并且应该将weblib作为依赖项

比我聪明的人也许能解释得更好

要使相对导入工作,所有包和子包都必须位于sys.path中-要实现这一点,您应该从顶级目录运行,如下所示:

C:\Users\phill\zigbot>python -m bot.zigbot

这将使您当前的工作目录(zigbot)可用于sys.path,并且子包将正确解析

相关问题 更多 >