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.
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
Related
I am trying to make an RPG game using python, and keep running into this error.
"partially initialized module (rpgLocations) has no attribute 'Tavern'"
Whenever I first run my program for testing, the file runs just fine, but then after a few times running it, it gives me this error. If I delete the file and create it again with a different name, it does the same thing. It works a few times then it doesn't.
No modules I imported have this attribute.
Tavern Function:
import main
def Tavern():
main.clear()
main.PlayerStatus.CurrentPlayerLocation = 'Tavern'
print('What would you like to do?\n\n\n')
while True:
main.pInput = input('1. Trade\n2. View quests\n3. gamble\n4. Look around\n5. Idk,\n6. Leave\n\n>')
if main.pInput == '1':
print('test works')
break
elif main.pInput == '6':
NavigationPanel()
in main.py, I import the file,
import rpgLocations
and call it later on
rpgLocations.Tavern()
To help diagnose this:
Is there any other files call rpgLocations within the same directory?
Also you seem to have a circular reference on your imports (main imports rpgLocations which imports main, and so on).
So I have a login script called login.py. When user log in, script will create a user session and execute main.py and close login.py. How to do this?
I'm a little confused by what you need help with but try this:
from fileName import function_you_want
Ideally you don't want a script to run on an import. It can cause some unexpected things to happen. At the bottom of main.py I would use this:
if __name__ == "__main__":
call_your_function()
This way you can do tests by running the script directly or calling a specific method from another py file without running the script.
What you can do is import that file main.py like import main. If you want everything from that file, from main import *
Then, after the user logins, destroy your main window using <Tk>.destroy() and then call your function.
I've got a script where I want to import a dict from a file and then use it to execute functions.
The file codes.py is as follows:
rf_433mhz = {
"0x471d5c" : sensor_LaundryDoor,
}
And the file it's using is as follows:
#!/usr/bin/python
import mosquitto
import json
import time
def sensor_LaundryDoor():
print "Laundry Door Opened"
mqttc.publish("actuators", json.dumps(["switch_HallLight", "on"]))
from codes import rf_433mhz
but I'm getting a NameError.
Traceback (most recent call last):
File "sensors.py", line 11, in <module>
from codes import rf_433mhz
File "/root/ha/modules/processing/codes.py", line 2, in <module>
"0x471d5c" : sensor_LaundryDoor,
NameError: name 'sensor_LaundryDoor' is not defined
Is there any way to do what I'm trying to do? It seems to be getting stuck on not having the function inside codes.py
I'm trying to call sensor_LaundryDoor() as follows
def on_message(msg):
inbound = json.loads(msg.payload)
medium = inbound[0]
content = inbound[1]
if str(medium) == "433mhz":
try:
rf_433mhz[str(content)]()
except:
print "Sorry code " + content + " is not setup"
import isn't include. It won't dump the source code of codes.py into your script; rather, it runs codes.py in its own namespace, almost like a separate script, and then assigns either the module object or specific module contents to names in the namespace the import is in. In the namespace of codes.py, there is no sensor_LaundryDoor variable.
The way you're dividing the code into modules isn't very useful. To understand codes.py, you need to understand the other file to know what sensor_LaundryDoor is. To understand the other file, you need to understand codes.py to know what you're importing. This circular dependency would negate most of the benefit of modularizing your code even if it wasn't an error. Reorganize your code to fix the circular dependency, and you'll probably fix the NameError as well.
The problem is that in your dictionary that you're importing, you're setting the value of 0x471d5c to a variable that was either not defined, or not defined in that scope.
An example of this would be like:
Codes.py
#!/usr/bin/python
sensor_LaundryDoor = 'foo'
rf_433mhz = {
"0x471d5c" : sensor_LaundryDoor,
}
Main files
#!/usr/bin/python
from test import rf_433mhz
print rf_433mhz["0x471d5c"]
There are hacky ways to solve this but it looks like the real issue is that you're trying to write C-style code in Python. The Python way to do things would be to import sensor_LaundryDoor in codes.py before using it, and if this introduces a circular reference then that's a design issue.
Maybe you need three modules, events.py with your main loop which imports the dict from codes.py which imports the functions from sensors.py.
I am getting back into python and I'm having a really basic issue....
My source has the following...
def calrounds(rounds):
print rounds
When I run this through the shell and try to call calrounds(3) I get..
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
calrounds(3)
NameError: name 'calrounds' is not defined
Its been awhile since I've used python, humor me.
Did you import your source first?
It says that the first line of your program is calling calrounds with a parameter 3. Move that below your function definition. The definition needs to be before you call the function. If you are using python 3.0+ you need parenthesis for the print statement.
>>> def calrounds(rounds):
print(rounds)
>>> calrounds(3)
3
The first thing to do is to look at how you're calling the function. Assuming it's in myModule.py, did you import myModule or did you from myModule import calrounds? If you used the first one, you need to call it as myModule.calrounds().
Next thing I would do is to make sure that you're restarting your interpreter. If you have imported a module, importing it again will not reload the source, but use what is already in memory.
The next posibility is that you're importing a file other than the one you think you are. You might be in a different directory or loading something from the standard library. After you import myModule you should print myModule.__file__ and see if it is the file you think you're working on. After 20 years of programming, I still find myself doing this about once a year and it's incredibly frustrating.
Finally, there's the chance that Python is just acting up. Next to your myModule.py there will be a myModule.pyc - this is where Python puts the compiled code so it can load modules faster. Normally it's smart enough to tell if your source has been modified but, occassionally, it fails. Delete your .pyc file and restart the interpreter.
I have 3 python files.(first.py, second.py, third.py) I'm executing 2nd python file from the 1st python file. 2nd python file uses the 'import' statement to make use of 3rd python file. This is what I'm doing.
This is my code.
first.py
import os
file_path = "folder\second.py"
os.system(file_path)
second.py
import third
...
(rest of the code)
third.py (which contains ReportLab code for generating PDF )
....
canvas.drawImage('xyz.jpg',0.2*inch, 7.65*inch, width=w*scale, height=h*scale)
....
when I'm executing this code, it gives error
IOError: Cannot open resource "xyz.jpg"
But when i execute second.py file directly by writing python second.py , everything works fine..!!
Even i tried this code,
file_path = "folder\second.py"
execfile(file_path)
But it gives this error,
ImportError: No module named third
But as i stated everything works fine if i directly execute the second.py file. !!
why this is happening? Is there any better idea for executing such a kind of nested python files?
Any idea or suggestions would be greatly appreciated.
I used this three files just to give the basic idea of my structure. You can consider this flow of execution as a single process. There are too many processes like this and each file contains thousandth lines of codes. That's why i can't change the whole code to be modularize which can be used by import statement. :-(
So the question is how to make a single python file which will take care of executing all the other processes. (If we are executing each process individually, everything works fine )
This should be easy if you do it the right way. There's a couple steps that you can follow to set it up.
Step 1: Set your files up to be run or imported
#!/usr/bin/env python
def main():
do_stuff()
if __name__ == '__main__':
The __name__ special variable will contain __main__ when invoked as a script, and the module name if imported. You can use that to provide a file that can be used either way.
Step 2: Make your subdirectory a package
If you add an empty file called __init__.py to folder, it becomes a package that you can import.
Step 3: Import and run your scripts
from folder import first, second, third
first.main()
second.main()
third.main()
The way you are doing thing is invalid.
You should: create a main application, and import 1,2,3.
In 1,2,3: You should define the things as your functions. Then call them from the main application.
IMHO: I don't need that you have much code to put into separate files, you just also put them into one file with function definitions and call them properly.
I second S.Lott: You really should rethink your design.
But just to provide an answer to your specific problem:
From what I can guess so far, you have second.py and third.py in folder, along with xyz.jpg. To make this work, you will have to change your working directory first. Try it in this way in first.py:
import os
....
os.chdir('folder')
execfile('second.py')
Try reading about the os module.
Future readers:
Pradyumna's answer from here solved Moin Ahmed's second issue for me:
import sys, change "sys.path" by appending the path during run
time,then import the module that will help
[i.e. sys.path.append(execfile's directory)]