Embed referenced before assignment - python

when I try running the code blow, I keep getting an error code that embed is already referenced even if I don't send the message ".help". Could any of you guys help me thanks.
import discord
import asyncio
from discord.ext import commands
client=discord.Client()
cliet=commands.Bot(command_prefix='.')
#client.event
async def on_ready():
print('help.py sucessfully loaded')
activity = discord.Activity(name='command watching for', type=discord.ActivityType.watching)
client = discord.Client(activity=activity)
#client.command()
async def help(ctx):
embed=discord.Embed(title="Title Here", description="Random Text Here", color=discord.Color.orange()), embed.set_footer(text="Inseart footer here"), embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url),
await ctx.channel.send(embed=embed)```

Not knowing a language is quite bad if you want to make something with the language.
Here is a minimal example of your problem:
class MyClass:
def __init__(self, arg):
self.arg = arg
def hello(self):
return "owo"
def my_func():
my_class = MyClass(1, my_class.hello()) # here, you we are trying to use `my_class` while assigning it at the same time which leads to the error.
my_func()
a more normal way such error is raised is
def my_func(x):
if x > 3:
y = 1 # if x is less than or equal to 3, y will not be assigned
return y # so what to return now? this will raise UnboundLocalVariable error
my_func(5) # works fine
my_func(100) # works fine
my_func(1) # oops, error
set_footer, set_author are bound methods of Embed object. You need an instance of it to use that. You would do these in separate lines
class MyClass:
def __init__(self, arg):
self.arg = arg
def hello(self):
return "owo"
def my_func():
my_class = MyClass(1)
my_class.hello() # now works!
my_func()
I won't be giving you the correct code for your specific problem, understand your problem, and fix it yourself.

See this line. (I added a few spaces to improve the readability)
embed = discord.Embed(title="Title Here", description="Random Text Here", color=discord.Color.orange()), embed.set_footer(text="Inseart footer here"), embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url),
What this is doing is creating a tuple, with a discord.Embed, followed by the return result of embed.set_footer, followed by the return result of embed.set_author. If we strip out the arguments, it basically comes down to this:
embed = discord.Embed(...), embed.set_footer(...), embed.set_author(...)
In basically every language, the right side of the assignment is evaluated first, and then set to the left side. This causes the method invocations to fail, because embed does not exist yet. You probably don't want embed to be a tuple anyway.
What you really want is this:
embed = discord.Embed(title="Title Here", description="Random Text Here", color=discord.Color.orange())
embed.set_footer(text="Inseart footer here")
embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url)
This creates the embed object first, and actually sets it to an Embed, and then runs the methods that set the other things.

I think you might use the command line
client= commands.Bot(command_prefix='.', help_command=None)
So there is not a default command message and you can use your own command.

Related

Python: How do I refactor and structure code in this scenario?

I'm quite stuck on structuring the code in this scenario. Can anyone help me with this?
| module.py
import asyncio
class Server:
def __init__(self):
self.d = {}
#classmethod
async def create(cls):
self = cls()
await self.func()
return self
async def func(self):
await asyncio.sleep(5) # Some other async code here
self.a = 12
def reg(self, ev):
def decorator(func):
self.d[ev] = func()
retun func
return decorator
def reg2(self, ev, func):
self.d[ev] = func
| main.py
import asyncio
from module import Server
async def main():
ser = await Server.create()
# This would be another way... but i find the other way one neater
serv.reg2('msg', some_handler)
# I want to decorate and register this using
# reg func; but since object is not created yet
# how do i acomplish this?
# #ser.reg('msg')
async def some_handler():
...
if __name__ == "__main__":
asyncio.run(main())
Some key points of my aim:
The function 'some_handler' is never used other than the time for register. That is, the function soley exists to be registered and is not used anywhere else.
Since Server class needs an asynchronous initialisation, it cannot be done globally.
(I dont know whether this point is helpful) Generally only one Server instance is created for a single program. There wont be any other instance even in other modules.
How do I model my code to satisfy this senario? I have mentioned an alternate way to register the function, but I feel I am missing something, as some_handler isn't used anywhere else. I have thought about making Server class into a metaclass to do registering and converting the main() and some_handler() as parts of the metclass's class but I'm seeking for different views and opinions.

Async function in class - Call it from another file?

I have a project that includes me using some SQL, I am wondering how can I call a function in the DB file?
class testing_db(commands.Cog):
def __init__(self, bot):
self.bot=bot
async def create_db_pool():
conn = await asyncpg.create_pool(database="db", user="user", host="nunyabusiness", password=DB_PW)
async def get_account_id(other_id):
mhm = "Do whatever I do here (I know how to do it but not call it from another file)"
loop.run_until_complete(create_db_pool())
def setup(bot):
bot.add_cog(testing_db(bot))
I'm not sure if this is the best/right way, but this is the first result on google so I wanted to share my workaround.
Add a function called run_main or whatever you want to call it. The function just needs to return your async run command:
def run_main():
return asyncio.run(main())
You can then call the run_main() function as normal from outside this file. Of course, substitute main() as necessary.
In your case, I would assume it's along the lines of adding a method like this:
def run_get_account_id(other_id):
return get_account_id(other_id)
Then import that method like normal. Note that this is probably a blocking call. I'm feeding a list to my main() so all the async stuff is happening inside main(). I would assume if you call run_get_account_id() individually, you will not get async behavior.

Decorators in class methods

I'm trying to apply decorator from another class on method in my class...
it is my implementation of this Telegram API wrapper library:
https://github.com/eternnoir/pyTelegramBotAPI
But in my example want to use it not from script - but as method of class like that:
class Bot:
def __init__(self, key):
self.key = key
self.bot=telebot.TeleBot(key)
def start(self):
self.bot.polling()
# Handle '/start' and '/help'
#self.bot.message_handler(commands=['help', 'start'])
def send_welcome(self,message):
self.bot.reply_to(message, """\
Hi there, I am EchoBot. \
I am here to echo your kind words back to you. \
Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
#self.bot.message_handler(func=lambda message: True)
def echo_message(message):
self.bot.reply_to(message, message.text)
All self are highlighted ... and certainly not working - will be glad if someone can explain what im doing wrong?
The original example trying to customize is:
import telebot
bot = telebot.TeleBot("TOKEN")
#bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
bot.reply_to(message, "Howdy, how are you doing?")
#bot.message_handler(func=lambda message: True)
def echo_all(message):
bot.reply_to(message, message.text)
bot.polling()
for those who might need it - solution i found - was to put the functions inside Ctor - and not to apply decorators to class methods .... :
class Bot:
def __init__(self, key,greting):
self.key = key
self.bot=telebot.TeleBot(key)
self.greting=greting
# Handle '/start' and '/help'
#self.bot.message_handler(commands=['help', 'start'])
def send_welcome(self, message):
self.bot.reply_to(message,self.greting )
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
#self.bot.message_handler(func=lambda message: True)
def echo_message(message):
self.bot.reply_to(message, message.text)
def start(self):
x = threading.Thread(name=self.greting, target=self.bot.polling,)
x.start()
self though a keyword is more of a placeholder variable name for the 1st argument for all methods that is always the instance object (except for classmethod where 1st argument is the class itself and staticmethod where there is neither)
For any method, even if you use this instead if self as 1st argument of any method, you can access all the object attributes as this.foo or methods as this.bar().
So technically, you don't have access to the object outside any method. The decorator is at the outer most level where you cannot access object (which is passed only to methods as the 1st argument)
A complex and unnecessary workaround I can think of is to write a static method that will help you catch the self object from argument and then access it's message_handler
I think that proper method is to use lambda functions. You can pass more than one parameter to it and get self from outer scope.
So, i finished with next sample
import telebot
class Telegram:
def __init__(self, token):
self.channel = telebot.TeleBot(token, parse_mode=None)
start_dict = dict(
function=lambda msg, obj=self: obj.start_handler(msg),
filters=dict(
commands=["start"],
)
)
self.channel.add_message_handler(start_dict)
self.channel.polling()
def start_handler(self, message):
print("START command")
test = Telegram("your-token-here")
You can run it from console and it will print START command every time you send /start to it.
You should set object of TeleBot() in method start().
import telebot
from decouple import config as key
class TelegramBot():
def bot(self):
bot = telebot.TeleBot(key('token'))
#bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, "Sup, Sani :)")
bot.polling(none_stop=True)
TelegramBotSpot().bot()
class Variaveis:
def __init__(self):
self.bot = telebot.TeleBot(token='')
#self.bot.message_handler(commands=["start"])
def _process_command_start(message):
self.process_command_start(message)
self.bot.polling(none_stop=True, timeout=123)
#----------------------------------------------------------------------------------------------------------------#
# Começando a programar :
def process_command_start(self, message):
self.bot.send_message(message.chat.id, 'ola mundo')
Variaveis()

expected an indented block python choregraphe

Hi I am new in Python and this is an error that many people have but I could'nt be helped by any other thread. The code is straight from this tutorial .
And it posts:[ERROR] behavior.box :FMBox::createPythonModule:0 _Behavior__lastUploadedChoregrapheBehaviorbehavior_1291762048__root__headnod_1: User class evaluation failed with the error:
('expected an indented block', ('', 19, 11, 'motionProxy.angleInterpolation(names,[0.0,1.0],times,True)\n'))
Thank you in advance
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
def onLoad(self):
#put initialization code here
pass
def onUnload(self):
pass
def onInput_onStart(self):
motionProxy=ALProxy("ALMotion")
names = ['HeadYaw','HeadPitch']
times = [[0.5],[0.5]]
motionProxy.angleInterpolation(names,[0.0,0.0],times,True)
for i in range(3):
motionProxy.angleInterpolation(names,[0.0,1.0],times,True)
motionProxy.angleInterpolation(names,[0.0,-1.0],times,True)
motionProxy.angleInterpolation(names,[0.0,0.0],times,True)
self.onStopped()
def onInput_onStop(self):
self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
self.onStopped() #activate the output of the box
Error says that your code is incorrectly indented.
For python you need to indent each block of code, like class body, for loop body, etc:
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
def onLoad(self):
#put initialization code here
pass
def onUnload(self):
pass
def onInput_onStart(self):
motionProxy=ALProxy("ALMotion")
names = ['HeadYaw','HeadPitch']
times = [[0.5],[0.5]]
motionProxy.angleInterpolation(names,[0.0,0.0],times,True)
for i in range(3):
motionProxy.angleInterpolation(names,[0.0,1.0],times,True)
motionProxy.angleInterpolation(names,[0.0,-1.0],times,True)
motionProxy.angleInterpolation(names,[0.0,0.0],times,True)
self.onStopped()
def onInput_onStop(self):
self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
self.onStopped() #activate the output of the box
Check this chapter from Dive Into Python - Indenting Code. Also just a note that code above is not complete, it is a part of something bigger, so you anyway can't just use this code alone to do something.

Python script is running. I have a method name as a string. How do I call this method?

everyone. Please see example below. I'd like to supply a string to 'schedule_action' method which specifies, what Bot-class method should be called. In the example below I've represented it as 'bot.action()' but I have no idea how to do it correctly. Please help
class Bot:
def work(self): pass
def fight(self): pass
class Scheduler:
def schedule_action(self,action):
bot = Bot()
bot.action()
scheduler = Scheduler()
scheduler.schedule_action('fight')
Use getattr:
class Bot:
def fight(self):
print "fighting is fun!"
class Scheduler:
def schedule_action(self,action):
bot = Bot()
getattr(bot,action)()
scheduler = Scheduler()
scheduler.schedule_action('fight')
Note that getattr also takes an optional argument that allows you to return a default value in case the requested action doesn't exist.
In short,
getattr(bot, action)()
getattr will look up an attribute on the object by name -- attributes can be data or member methods The extra () at the end calls the method.
You could get the method in a separate step, like this, as well:
method_to_call = getattr(bot, action)
method_to_call()
And you can pass arguments to the method in the usual way:
getattr(bot, action)(argument1, argument2)
or
method_to_call = getattr(bot, action)
method_to_call(argument1, argument2)
I'm not sure if it applies in your situation, but you may consider using a function pointer instead of manipulating the strings.
class Bot:
def work(self):
print 'working'
def fight(self):
print 'fightin'
class Scheduler:
def schedule_action(self,action):
bot = Bot()
action(bot)
scheduler = Scheduler()
scheduler.schedule_action(Bot.fight)
scheduler.schedule_action(Bot.work)
Which prints:
fightin
working
If you can do this, it will give you an error about a misspelled function at compile-time when the code is interpreted instead of during run-time. This could shorten your debug cycle for stupid data-entry errors, especially if the actions are done over a span of time. Nothing sucks more than running something overnight and discovering that you had a syntax error in the morning.
class Scheduler:
def schedule_action(self,action):
bot = Bot()
boundmethod = getattr(bot, action)
boundmethod()
def schedule_action(self,action):
bot = Bot()
bot.__getattribute__(action)()
You can also use a dictionary to map methods to actions. For instance:
ACTIONS = {"fight": Bot.fight,
"walk": Bot.walk,}
class Scheduler:
def schedule_action(self, action):
return ACTIONS[action](Bot())

Categories

Resources