Get argparse exec to properly load variables from python config file

Question:

I am trying to get Argparse exec should load the variables user_token and channel_id from the config.py file inputted by the user (--config-file argparse argument).

For whatever reason it will only load the main config file (from config import *) even when running the proper commands to load in another one besides the main:

I’ve tried to remove config import * and have parser() return user_token after the exec call but that ends up return None type. yet if i print out the result of config_file in it returns whatever was input into –config-file part of the command, meaning it’s parsing the command but not able to properly read the config.py file

python3 bot.py --config-file config1.py would run account1

python3 bot.py --config-file config2.py would run account2

config file template(all are located in same directory as main.py):

channel_id = XXXXX
user_token = "XXXXX"

main.py file:

from asyncio import sleep
import argparse
import discord, datetime
import tweepy
from config import *

def parser():   
    parser = argparse.ArgumentParser()
    parser.add_argument("--config-file", type=str, required=True)
    args = parser.parse_args()
    config_file = args.config_file
    exec(open(config_file).read())
    
parser()

class Client(discord.Client):
    active = True      

    async def pauseBump(self):
        self.active = False
        print("Bump paused.")

    async def continueBump(self):
        self.active = True
        print("Bump restored.")

    async def clean(self, user_message=None, bot_message=None):
        await sleep(3)
        if user_message is not None:
            await user_message.delete()
        if bot_message is not None:
            await bot_message.delete()
        print("Chat cleaned")

    async def send(self, ctx, content):
        message = await ctx.channel.send(f"{ctx.author.mention} {content}")
        print(f"Sent '{content}' to '{ctx.author}'")
        await self.clean(ctx, message)

    async def bumpCheck(self):
        channels_ids = []
        for server in self.guilds:
            for channel in server.channels:
                if str(channel.type) == 'text':
                    channels_ids.append(channel.id)
        print(channels_ids)
        #channels_ids = [channel.id for channel in channels]
        # Get a list of all chanells in the current server
        for channel_id in channels_ids:
            channel = self.get_channel(channel_id)
            async for message in channel.history(limit=50):
                if message.author != self.user:
                    if "react" in message.content.lower():
                        await message.add_reaction("N{THUMBS UP SIGN}")
            # Code from original auto-bump author
            if str(message.author) == "DISCORD_ADMIN_NAME":
                if "Bump done" in message.embeds[0].description:
                    now = datetime.datetime.utcnow()
                    two = datetime.timedelta(hours=2)
                    min = datetime.timedelta(minutes=1)

                    difference = now - message.created_at
                    difference = two - difference + min
                    print(f"Time until next bump {difference}")

                    return difference.seconds
        return 120
        # Code from original auto-bump author
    async def bump(self):
        self.diff = await self.bumpCheck()
        await sleep(self.diff)
        channel = self.get_channel(channel_id)
        command = await channel.send("bump")
        print("Server bumped")
        return command

    async def on_ready(self):
        print(f"Logged as {self.user}")
        while self.active == True:
            command = await self.bump()
            await self.clean(command)

    async def on_message(self, message):
        if message.author == self.user:
            if message.content == "!pause":
                await self.pauseBump()
                await self.send(message, "Bot is paused :sleeping:")

            elif message.content == "!continue":
                await self.continueBump()
                await self.send(
                    message,
                    f"Bump is activated, next bump in {self.diff} seconds :hourglass_flowing_sand:",
                )

Client().run( user_token, bot=False)
Asked By: JP Codes

||

Answers:

This works, but i DO NOT recommend it! Do NOT use python files as config files by loading the content via exec. This can have unwanted effects, depending on what is in the config.py file. Use a json file and override the imported config variables.

from asyncio import sleep
import argparse
import discord, datetime
import tweepy
from config import *

def parser():   
    parser = argparse.ArgumentParser()
    parser.add_argument("--config-file", type=str, required=True)
    args = parser.parse_args()
    config_file = args.config_file
    return open(config_file).read()
    
exec(parser())
Answered By: phibel
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.