0

I am trying to run a chat bot of sorts that is capable of creating new commands whilst the program is running. To do this I am keeping all the commands in a second python script and using the main script to edit the commands.py file whilst the chat bot is still running.

The issue...

I am able to have both scripts access each other using import main and then main.functionName() to call the function. However, when I try to call a function in commands.py from main.py, then use the function called to call another function back in main.py I get an error saying

AttributeError: module 'main' has no attribute 'exampleFunction' 

For example the following code;

TESTING.py

import TESTING2

def runme(inp):
    print(inp)
    startOver()

print("begin")
TESTING2.startOver()

TESTING2.py

import TESTING

def startOver():
    userInput = input("Enter text at your own risk... ")
    TESTING.runme(userInput)

Produces the following;

begin
Traceback (most recent call last):
  File "C:\Users\harry\Desktop\TESTING.py", line 1, in <module>
    import TESTING2
  File "C:\Users\harry\Desktop\TESTING2.py", line 1, in <module>
    import TESTING
  File "C:\Users\harry\Desktop\TESTING.py", line 8, in <module>
    TESTING2.startOver()
AttributeError: module 'TESTING2' has no attribute 'startOver'

The desired outcome would be a continuous loop of entering an input and then the text being printed as if one seamless script.

Is this possible? If so how do I do it - or is there a better way to achieve the same goal?

Many thanks.

  • The way you've constructed this doesn't make much sense. You should separate functionality you want to import from where it is being run. Just create a module my_module and place both runme and startOver there. Then in TESTING2 do: from my_module import runme, startOver – Karl Nov 10 '18 at 08:22
  • The point of this program is to be able to essentially edit itself. I want to separate the commands from the main script so that more commands can be simply added on the bottom of commands.py while main.py is running and then be used by main.py (unless it is possible to edit and update a python script in real time while running). The example above is simply that - an example. It's a simple code that causes the same error I get when running the actual program :) – Harry Cossie Nov 10 '18 at 09:37
  • Ok, so let's say while main.py is running I add a function my_new_fuction to commands.py. Now what? Do you want to now use this in main.py? If so, how? You use the "input" function above, so is that how you plan to tell main to execute my_new_func? – Karl Nov 10 '18 at 13:27

1 Answers1

0

So, I'll have a go at giving you something that might solve your problem. Essentially what you are doing is constructing a circular dependency: commands.py is written by main.py, main.py depends on commands.py for its functions. There is almost certainly a way to solve your problem without introducing such a circular dependency, but I would need to know more in order to suggest something.

If you are sure you want to do it like this, you could use importlib.reload, which tells python to reload a module that you've already imported. In other words, if you've added a new function to commands.py since calling the original import, calling reload will now make this function available.

As a small example, try setting up commands.py and main.py scripts as follows:

#commands.py
def func1():
    print(1)

and:

#main.py
import commands
commands.func1()

input("hit enter once you've edited commands.py")

from importlib import reload
commands = reload(commands)
commands.func2()

run main.py and when you get to the input part, open up commands.py and change it to look like this:

#commands.py
def func1():
    print(1)

def func2():
    print(2)

Now hit "enter" in the running main.py script. You should see the result of func2printed to the terminal.

Note however also that reload doesn't necessarily act the way you would expect and could cause some strange and explainable things to happen. For more info, see this post: https://stackoverflow.com/a/438845/141789

Karl
  • 5,573
  • 8
  • 50
  • 73