itzFlubby
itzFlubby

Reputation: 2289

'second_file' has no attribute 'hello' -- Discord Python Bot

I ran into the following problem :

First_File:

import discord
import second_file 
client = discord.Client()
[...]
@client.event
async def on_message(message):
    if message.content.lower().startswith("!hi"):
        await second_file.hello()

Second_File:

from first_file import client
from first_file import on_message
async def hello(client, on_message):
    await client.send_message(message.channel, "Hiii <3!")

And now I get the error message: module 'second_file' has no attribute 'hello'. Why won't it call the function?

Upvotes: 2

Views: 88

Answers (1)

Peter G
Peter G

Reputation: 2821

This is quite a cryptic error message compared to what's actually happening. You're attempting to import from both files at the same time and that causes issues. Whenever you import, the complete file will be interpreted, even though you're using from file import thing. To be more specific to your case, await second_file.hello() fails because second_file hasn't been fully imported yet when you get to it.

Here's what's being executed and why it fails (you can verify this from the stack trace that you get when you try to import the file in a python3 REPL):

  1. import second_file in first_file, stops interpretation of first_file and triggers a complete interpretation of second_file.
  2. from first_file import client stops interpretation of second_file and triggers a complete interpretation of first_file.
  3. This time, import second_file is skipped (otherwise you'd get an infinite loop). Continue interpreting first_file until...
  4. await second_file.hello(): ignoring the syntax error where hello() accepts two arguments, notice the interpreter doesn't know about hello() yet. Obviously, this is a syntax error since you're using something you haven't defined yet!

To fix this, use the architecture you've already created. Just drop the two import statements at the start of second_file. I've also taken the liberty of adding the message argument it seems you forgot. Not sure why you even need the on_message function to be passed in, but to be fair I don't know your use case.

first_file

import discord
import second_file 
client = discord.Client()
[...]
@client.event
async def on_message(message):
    if message.content.lower().startswith("!hi"):
        await second_file.hello(client, on_message, message)

second_file

async def hello(client, on_message, message):
    await client.send_message(message.channel, "Hiii <3!")

Upvotes: 1

Related Questions