skip to Main Content

I’m have a script ‘zigbot.py’ which was working, but I’m restructuring to dockerize and now I’m questioning my ability to code at all. What I’m trying to do is have a telegram-bot container, and a ‘web’ container (FLASK), and a nginx container.

Next to zigbot.py I have a folder – ‘bot’, which has many of my scripts and functions in. Upon trying from bot.somescript import a_function I am getting error after error.

Project structure

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

When running the code below, I get a whole range of strange errors – the one listed below shows ImportError – it can’t find ‘onboard’ in funcs, but its definitely there. Before the restructure, this was working. If I comment out ‘onboard’ it errors on every function in the list.

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 "ZigBotbotbotfuncs.py", line 2, in <module>
    from zigbot.web.app import db, app
  File "ZigBotbotzigbot.py", line 15, in <module>
    from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, 
ImportError: cannot import name 'onboard'

So I tried adding a .bot.conversation for (relative?) import, but this produces an even weirder error. I’ve included the code, the error, then the function I’m trying to import below:

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

conversations.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)

Finally, I think I’m getting closer to the problem, I go back to the way I think it’s supposed to be imported. From bot.funcs import x,y,y… I look in funcs.py and this is how its importing some other code from my Flask web app, but it doesn’t like it.

funcs.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 "ZigBotbotbotfuncs.py", line 2, in <module>
    from web.app import db, app
ModuleNotFoundError: No module named 'web'

So I change the import to go up a level since web is two levels above bot – which contains the script I’m importing to. So zigbot>bot>bot>funcs.py trying to import from 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 "ZigBotbotbotfuncs.py", line 2, in <module>
    from ..web.app import db, app
ValueError: attempted relative import beyond top-level package

This obviously doesn’t work either. Given my structure of having bot and web how do I get this to work? I even tried pulling the scripts out of the second ‘bot’ folder but I get the same issues. Finally, my weirdest error which might provide a clue to what I’m doing wrong, if I change the import on funcs.py to go one level up, rather than two, I get an even stranger traceback.

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:UsersphillPycharmProjectsZigBotbotbotfuncs.py", line 2, in <module>
    from .web.app import db, app
ModuleNotFoundError: No module named 'bot.web'

For clarity I removed some ‘C:Usersphill’ from the tracebacks before realising it was pointless to remove that.

2

Answers


  1. 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.

    Login or Signup to reply.
  2. For relative imports to work all the packages and subpackages must be in the sys.path – to achieve this you should run from the top-level directory as in:

    C:Usersphillzigbot>python -m bot.zigbot
    

    This will make your current working dir (zigbot) available to sys.path and the subpackages will be resolved correctly

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search