skip to Main Content

yet another thread, but I don’t really get it…
I have an application (telegram python bot) with a lot of CONSTANTS in it, so I did a bit of a structure here:

bot/
    api.py
    bot.py
    constants.py
    functions.py
    keyboards.py

Main execution file is: bot.py

Below is the imports from those files:

# bot.py

import os, logging, re
import constants as c
from telegram import Update
from telegram.ext import filters, ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, ConversationHandler, CallbackQueryHandler
from keyboards import START_KEYBOARD, INFO_KEYBOARD, SETTINGS_KEYBOARD, PUNCH_KEYBOARD
import api as a
import functions as f
# api.py

import requests, openai
import constants as c
import functions as f
# constants.py

import os
import datetime as d
import functions as f
# functions.py

import api as a
import constants as c
from typing import Literal
from datetime import datetime
from telegram import Update
# keyboards.py

from telegram import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
import constants as c
bot_1  | Traceback (most recent call last):
bot_1  |   File "/opt/app/bot.py", line 2, in <module>
bot_1  |     import constants as c
bot_1  |   File "/opt/app/constants.py", line 3, in <module>
bot_1  |     import functions as f
bot_1  |   File "/opt/app/functions.py", line 1, in <module>
bot_1  |     import api as a
bot_1  |   File "/opt/app/api.py", line 58, in <module>
bot_1  |     def req_tes_headers(host=c.TES_OAUTH_HOST ,token=''):
bot_1  |                              ^^^^^^^^^^^^^^^^
bot_1  | AttributeError: partially initialized module 'constants' has no attribute 'TES_OAUTH_HOST' (most likely due to a circular import)

So my question is why the **** I still getting this error?

2

Answers


  1. Your constants module has no reason to import any other module AFAICT. By importing functions (which itself depends on constants defined in constants to define defaults for some of the functions it provides), you end up creating a circular import which requires elements from both modules during the definition of things in those modules, which causes your problem.

    If the constants module is made into a leaf module in the package (imported by other modules, but not itself importing anything from other modules in the package), your problem should disappear; the first thing to import constants will import it completely before it tries to use anything from it (e.g. functions using it to set defaults for one of the functions it defines). You’ll still have some circular imports involved (e.g. api importing functions and vice-versa), but so long as none of them require anything from the module they import at import time, you should be okay.

    Login or Signup to reply.
  2. This is due to circular import.
    Here’s how it happens:

    1. bot.py imports constants.py.
    2. constants.py imports functions.py.
    3. functions.py imports api.py.
    4. api.py imports constants.py again,
      Constants.py is not fully initialized yet because it’s waiting for functions.py to be initialized, which in turn is waiting for api.py to be initialized. This is the circular import.

    To fix this, you need to refactor your code to remove the circular dependency. One way to do this is to move the import statements inside the functions that use them.

    import requests, openai
    import functions as f
    
    def req_tes_headers(host='', token=''):
        import constants as c
        if not host:
            host = c.TES_OAUTH_HOST
        ...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search