Reload self-made module - python

Files:
File 1: metrobot.py
File 2: irc.py
File 3: cmd.py
MetroBot.py starts irc.py, irc.py makes a while loop which then uses cmd.py.
I try reloading the cmd module from irc.py. After i've reloaded it, the changes in cmd.py still won't take effect.
Reload code snippet:
if ":!reload" in self.buf:
reload(sys.modules['cmd'])
I've also tried
reload(cmd)
None of the two works.
Anyone know what cause the reload to not work, or another simple way? This script is meant to be running at all times.

I created the following three mini-scripts to test this and it works:
bot.py:
import irc
def start():
irc.run()
irc.py:
import cmd, time
def run():
while 1:
print cmd.dothis()
reload(cmd)
time.sleep(1)
cmd.py:
def dothis():
return 1
Now if you run bot.start() it will print "1" once a second and if I then edit cmd.py at some point to say return 2 it prints "2".. Obviously I'm imagining this is a whole way simpler than whatever code you're having, but you'll need to post some samples to help us answer you better. Or try breaking your code down and testing the reload with a stripped down version of your code.

Related

Why is my python class being executed twice?

I am currently trying to write an script which takes an user input and then prints it out through a class which is located in another file. But when running my script I have to give the programm the input twice which is then being printed out thrice because of an weird reason. I also searched up some other similar questions on stackoverflow but none of them helped me fixing my problem.
This is the code in the first file:
#this is main.py
global test_input
test_input = input('give me an input: ')
if 'i like cookies' in test_input:
from test import *
test_class.test()
This is the code in the second file:
#this is test.py
class test_class():
def test():
from main import test_input
print(test_input)
What the output looks like after running the script:
give me an input: i like cookies
give me an input: i like cookies #this second input is created because the function is being executed twice. In this example I would've typed in i like cookies twice
i like cookies
i like cookies
i like cookies
What the ouput should look like:
give me an input: i like cookies
i like cookies
I would be very very glad if someone could help me out with solving this problem and explaining to me what I've made wrong:)
Thank's for every suggestion and help in advance:)
It is punishing you for bad programming practices. ;) The issue is that, when you run a program, that module is not considered to be imported. So, when you get into test_class.test(), your from main statement actually causes your main program to be loaded AGAIN. It will do the input call again, and will call test_class.test() again. This time, main has already been imported, so it doesn't need to do it again, and thing go normally.
It is horrible practice for a submodule to try to import something from a main module. If your module function needs a value, then pass it as a parameter.

Running a .py file in a loop

I am currently trying to run a .py file but in a loop.
Just for a test I am using
I = 0
while I<10:
os.pause(10)
open(home/Tyler/desktop/test.py)
I = I + 1
I am sure this is a very simple question but I can't figure this one out.
I would also like to add in the very end of this I have to make this run infinitely and let it run for some other things.
There are a few reasons why your code isn't working:
Incorrect indentation (this may just be how you copied it on to StackOverflow though).
Using os without importing it.
Not using quotes for a string.
Mis-using the open function; open opens a file for reading and/or writing. To execute a file you probably want to use the os.system.
Here's a version that should work:
import os
i = 0
while i < 10:
os.pause(10)
os.system("home/Tyler/desktop/test.py")
i += 1
Python is indentation-sensitive, and your code is missing indentation
after the while statement!
Running the open command will not run the Python script. You can
read what it does here in the docs:
https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
This stack overflow question talks about how to run Python that's
stored in another file
How can I make one python file run another?
I recommend wrapping the code you want to run in a function, e.g.
def foo():
print 'hello'
and then saving this in foo.py. From your main script, you can then do:
import foo
i = 0
while i < 10:
foo.foo()
i += 1
If you want to run something in an infinite loop, you need the condition for the while loop to always be true:
while True:
# do thing forever
A note on importing: The example I have given will work if the foo.py file is in the same directory as the main Python file. If it is not, then you should have a read here about how to create Python modules http://www.tutorialspoint.com/python/python_modules.htm

reload the currently running python script

In python ,There is a reload method to reload an imported module , but is there a method to reload the currently running script without restarting it, this would be very helpful in debugging a script and changing the code live while the script is running. In visual basic I remember a similar functionality was called "apply code changes", but I need a similar functionality as a function call like "refresh()" which will apply the code changes instantly.
This would work smoothly when an independent function in the script is modified and we need to immediately apply the code change without restarting the script.
Inshort will:
reload(self)
work?
reload(self) will not work, because reload() works on modules, not live instances of classes. What you want is some logic external to your main application, which checks whether it has to be reloaded. You have to think about what is needed to re-create your application state upon reload.
Some hints in this direction:
Guido van Rossum wrote once this: xreload.py; it does a bit more than reload() You would need a loop, which checks for changes every x seconds and applies this.
Also have a look at livecoding which basically does this. EDIT: I mistook this project for something else (which I didn't find now), sorry.
perhaps this SO question will help you
Perhaps you mean something like this:
import pdb
import importlib
from os.path import basename
def function():
print("hello world")
if __name__ == "__main__":
# import this module, but not as __main__ so everything other than this
# if statement is executed
mainmodname = basename(__file__)[:-3]
module = importlib.import_module(mainmodname)
while True:
# reload the module to check for changes
importlib.reload(module)
# update the globals of __main__ with the any new or changed
# functions or classes in the reloaded module
globals().update(vars(module))
function()
pdb.set_trace()
Run the code, then change the contents of function and enter c at the prompt to run the next iteration of the loop.
test.py
class Test(object):
def getTest(self):
return 'test1'
testReload.py
from test import Test
t = Test()
print t.getTest()
# change return value (test.py)
import importlib
module = importlib.import_module(Test.__module__)
reload(module)
from test import Test
t = Test()
print t.getTest()
Intro
reload is for imported modules. Documentation for reload advises against reloading __main__.
Reloading sys, __main__, builtins and other key modules is not recommended.
To achieve similar behavior on your script you will need to re-execute the script. This will - for normal scripts - also reset the the global state. I propose a solution.
NOTE
The solution I propose is very powerful and should only be used for code you trust. Automatically executing code from unknown sources can lead to a world of pain. Python is not a good environment for soapboxing unsafe code.
Solution
To programmatically execute a python script from another script you only need the built-in functions open, compile and exec.
Here is an example function that will re-execute the script it is in:
def refresh():
with open(__file__) as fo:
source_code = fo.read()
byte_code = compile(source_code, __file__, "exec")
exec(byte_code)
The above will in normal circumstances also re-set any global variables you might have. If you wish to keep these variables you should check weather or not those variables have already been set. This can be done with a try-except block covering NameError exceptions. But that can be tedious so I propose using a flag variable.
Here is an example using the flag variable:
in_main = __name__ == "__main__"
first_run = "flag" not in globals()
if in_main and first_run:
flag = True
None of these answers did the job properly for me, so I put together something very messy and very non-pythonic to do the job myself. Even after running it for several weeks, I am finding small issues and fixing them. One issue will be if your PWD/CWD changes.
Warning this is very ugly code. Perhaps someone will make it pretty, but it does work.
Not only does it create a refresh() function that properly reloads your script in a manner such that any Exceptions will properly display, but it creates refresh_<scriptname> functions for previously loaded scripts just-in-case you need to reload those.
Next I would probably add a require portion, so that scripts can reload other scripts -- but I'm not trying to make node.js here.
First, the "one-liner" that you need to insert in any script you want to refresh.
with open(os.path.dirname(__file__) + os.sep + 'refresh.py', 'r') as f: \
exec(compile(f.read().replace('__BASE__', \
os.path.basename(__file__).replace('.py', '')).replace('__FILE__', \
__file__), __file__, 'exec'))
And second, the actual refresh function which should be saved to refresh.py in the same directory. (See, room for improvement already).
def refresh(filepath = __file__, _globals = None, _locals = None):
print("Reading {}...".format(filepath))
if _globals is None:
_globals = globals()
_globals.update({
"__file__": filepath,
"__name__": "__main__",
})
with open(filepath, 'rb') as file:
exec(compile(file.read(), filepath, 'exec'), _globals, _locals)
def refresh___BASE__():
refresh("__FILE__")
Tested with Python 2.7 and 3.
Take a look at reload. You just need to install the plugin an use reload ./myscript.py, voilĂ 
If you are running in an interactive session you could use ipython autoreload
autoreload reloads modules automatically before entering the execution of code typed at the IPython prompt.
Of course this also works on module level, so you would do something like:
>>>import myscript
>>>myscript.main()
*do some changes in myscript.py*
>>>myscript.main() #is now changed

How can I add a command to the Python interactive shell?

I'm trying to save myself just a few keystrokes for a command I type fairly regularly in Python.
In my python startup script, I define a function called load which is similar to import, but adds some functionality. It takes a single string:
def load(s):
# Do some stuff
return something
In order to call this function I have to type
>>> load('something')
I would rather be able to simply type:
>>> load something
I am running Python with readline support, so I know there exists some programmability there, but I don't know if this sort of thing is possible using it.
I attempted to get around this by using the InteractivConsole and creating an instance of it in my startup file, like so:
import code, re, traceback
class LoadingInteractiveConsole(code.InteractiveConsole):
def raw_input(self, prompt = ""):
s = raw_input(prompt)
match = re.match('^load\s+(.+)', s)
if match:
module = match.group(1)
try:
load(module)
print "Loaded " + module
except ImportError:
traceback.print_exc()
return ''
else:
return s
console = LoadingInteractiveConsole()
console.interact("")
This works with the caveat that I have to hit Ctrl-D twice to exit the python interpreter: once to get out of my custom console, once to get out of the real one.
Is there a way to do this without writing a custom C program and embedding the interpreter into it?
Edit
Out of channel, I had the suggestion of appending this to the end of my startup file:
import sys
sys.exit()
It works well enough, but I'm still interested in alternative solutions.
You could try ipython - which gives a python shell which does allow many things including automatic parentheses which gives you the function call as you requested.
I think you want the cmd module.
See a tutorial here:
http://wiki.python.org/moin/CmdModule
Hate to answer my own question, but there hasn't been an answer that works for all the versions of Python I use. Aside from the solution I posted in my question edit (which is what I'm now using), here's another:
Edit .bashrc to contain the following lines:
alias python3='python3 ~/py/shellreplace.py'
alias python='python ~/py/shellreplace.py'
alias python27='python27 ~/py/shellreplace.py'
Then simply move all of the LoadingInteractiveConsole code into the file ~/py/shellreplace.py Once the script finishes executing, python will cease executing, and the improved interactive session will be seamless.

Can't figure out how to invoke cProfile inside of a program

Sorry for the beginner question, but I can't figure out cProfile (I'm really new to Python)
I can run it via my terminal with:
python -m cProfile myscript.py
But I need to run it on a webserver, so I'd like to put the command within the script it will look at. How would I do this? I've seen stuff using terms like __init__ and __main__ but I dont really understand what those are.
I know this is simple, I'm just still trying to learn everything and I know there's someone who will know this.
Thanks in advance! I appreciate it.
I think you've been seeing ideas like this:
if __name__ == "__main__":
# do something if this script is invoked
# as python scriptname. Otherwise, gets ignored.
What happens is when you call python on a script, that file has an attribute __name__ set to "__main__" if it is the file being directly called by the python executable. Otherwise, (if it is not directly called) it is imported.
Now, you can use this trick on your scripts if you need to, for example, assuming you have:
def somescriptfunc():
# does something
pass
if __name__ == "__main__":
# do something if this script is invoked
# as python scriptname. Otherwise, gets ignored.
import cProfile
cProfile.run('somescriptfunc()')
This changes your script. When imported, its member functions, classes etc can be used as normal. When run from the command-line, it profiles itself.
Is this what you're looking for?
From the comments I've gathered more is perhaps needed, so here goes:
If you're running a script from CGI changes are it is of the form:
# do some stuff to extract the parameters
# do something with the parameters
# return the response.
When I say abstract out, you can do this:
def do_something_with_parameters(param1, param2):
pass
if __name__ = "__main__":
import cProfile
cProfile.run('do_something_with_parameters(param1=\'sometestvalue\')')
Put that file on your python path. When run itself, it will profile the function you want profiling.
Now, for your CGI script, create a script that does:
import {insert name of script from above here}
# do something to determine parameter values
# do something with them *via the function*:
do_something_with_parameters(param1=..., param2=...)
# return something
So your cgi script just becomes a little wrapper for your function (which it is anyway) and your function is now self-testing.
You can then profile the function using made up values on your desktop, away from the production server.
There are probably neater ways to achieve this, but it would work.

Categories

Resources