0

我有一个正在运行的脚本“zigbot.py”,但我正在重组为 dockerize,现在我完全质疑我的编码能力。我想要做的是有一个电报机器人容器、一个“网络”容器(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

运行下面的代码时,我得到了一系列奇怪的错误——下面列出的一个显示 ImportError——它在 funcs 中找不到“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)

最后,我认为我越来越接近问题,我回到我认为应该导入的方式。From bot.funcs import x,y,y... 我在 funcs.py 中查看,这就是它从我的 Flask Web 应用程序中导入一些其他代码的方式,但它不喜欢它。

函数.py

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

这显然也不起作用。鉴于我的结构bot以及web如何使其发挥作用?我什至尝试将脚本从第二个“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”,然后才意识到删除它是没有意义的。

4

2 回答 2

0

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

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

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

于 2019-10-03T12:59:55.213 回答
0

I think there's a fundamental flaw in your split if you have library dependencies across the boundary. Assuming that there are no imports of bot-modules in your web container, I would suggest breaking off the shared code into a module named weblib or something (alongside the bot-, nginx- and web-folders).

You still should not try to import across would-be container boundaries however, so just make sure weblib is in your path or installed in your virtual environment or however you want to handle it. Basically, bot and web should run in separate environments and should have weblib as a dependency.

Someone wiser than me might be able to explain it better.

于 2019-10-02T11:18:26.153 回答