0

Original question:

I have a Tkinter button which upon pressing will execute a script.py file.

#-*- coding: utf-8 -*-
from Tkinter import *
master = Tk()
def callback():
    execfile("script.py")
b = Button(master, text="OK", command=callback)
b.pack()
mainloop()

The script.py is a 2D animation which will open a window for animation.

"""
A simple example of an animated plot
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

x = np.arange(0, 2*np.pi, 0.01)        # x-array
line, = ax.plot(x, np.sin(x))

def animate(i):
    line.set_ydata(np.sin(x+i/10.0))  # update the data
    return line,

#Init only required for blitting to give a clean slate.
def init():
    line.set_ydata(np.ma.array(x, mask=True))
    return line,
ani = animation.FuncAnimation(fig, animate, np.arange(1,200),init_func=init,interval=25, blit=True)
plt.show()

When I run the Tkinter code above and pressed button to call the animation, animation will only show first frame. In other words, animation will not be played. But if script.py is run from command line, animation plays correctly. The question is, how to make animation plays when run from the Tkinter code?

  • Have you tried using something like `os.system()` or `subprocess.call()`? The [doc for `execfile`](https://docs.python.org/2/library/functions.html#execfile) says "if both dictionaries are omitted, the expression is executed in the environment where execfile() is called," which sounds like it could cause trouble. – TigerhawkT3 May 01 '15 at 07:47
  • Thanks for the lead! I will check your link to `execfile` and also learn about `os.system` and `subprocess.call` more. – user3852107 May 01 '15 at 08:56

2 Answers2

0

I was not able to reproduce the behavior you encounter, execution breaks in init.

File "script.py", line 19, in init
  line.set_ydata(np.ma.array(x, mask=True))

However, you could redesign your application to rely on more conventional import to execute python code from another file. You can alter your script.py this way

#script.py
def script():
    #previous script.py content

if __name__ == '__main__':
    script()

This way, if you run the file, you match the __name__ == '__main__' clause and your file will run on its own. When you import it, the script function will be defined but not executed. From your tkinter program, you just need to

import script

def callback():
    script.script()
FabienAndre
  • 4,514
  • 25
  • 38
  • I checked my script.py and it seems to be fine. Could it be the version incompatibility? I am using Anaconda package with Spyder, Python 2.7, NumPy 1.7.1, Matplotlib 1.3.1. Would you mind telling me the error messages? Also I tried your method but the movie still don't play. Also the first frame will not be drawn with this method. Sorry for updating your post to reflect the suggestion you made. I do somehow understand that the way I'm doing it is not conventional, which I can see from @FabienAndre 's response mentioning the conventional `import` part, and also from @TigerhawkT3 's comment. – user3852107 May 04 '15 at 08:57
0

I unexpectedly found a way to get around this animation problem, and thought that it's worth writing down.

If in the script.py file, I return a global variable from the execfile function, the animation callback by the TK button will now play correctly.

from Tkinter import *
master = Tk()
def callback():
    variables= {} #add a variable with witch execfile can return
    execfile("simple_anime.py",    variables)
b = Button(master, text="OK", command=callback)
b.pack()
mainloop()

This way it will work. And, I just realized, this is what TigerhawkT3 mentioned in his answer. I looked into subprocess but I'm still not sure how to use it in this case.

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43