How to switch to a python subprocess created by IPython (on OS X)?
When I use IPython along with the -wthread
option, it spawns a python subprocess, which appears as a Mac OS X application.
My problem is that when I send commands to that application (for example plotting with matplotlib
), the window is updated behind all my other windows. I would like to be able to call a python command to switch this python window to the front (I do that manually with ⌘-tab, but I have to find the python application first, and there might be several ones).
Is there a python script to detect which application IPython has spawned, and how to then automatically switch to it in OS X?
(I'm stating the problem in OS X, but the issue should be similar on other systems).
Edit: let me break this down in two problems:
- how to know which Mac OS X application python is running in? (probably possible with some IPython witchery)
- how to tell Mac OS X t开发者_运维问答o put the focus on that application? (maybe using applescript)
Could be either:
Making a new python script that tracks grandchild processes of another script might be tricky. The IPython documentation has an example to monitor spawned processes by pid; JobControl. JobControl only kills the processes but I imagine adding a command to change window focus would be fairly easy.
From what I've read, the Tk gui does not properly set window focus on macs. If your 'matplotlib' or otherwise uses the Tk gui, this may be the problem. -source-
I am not very familiar with OS X, so either run with those, clarify your situation or let me know if I'm too far off.
Here is my full solution, with an IPython magic function.
Install appscript (see this question about switching apps programmatically in OS X), and put the following code in a script called activate.py
in your ~/.ipython
folder.
import appscript
import sys
appscript.app(pid=int(sys.argv[1])).activate()
Now, edit your ~/.ipython/ipy_user_conf.py
configuration file and define the magic function:
def wxactivate(self, arg):
import wx
pid = wx.GetProcessId()
ip = self.api
import os
here = os.path.dirname(__file__)
import subprocess
subprocess.Popen([os.path.join(here, 'activate.py'), str(pid)])
Now you just have to register this magic IPython function by putting the following somewhere in that same configuration file:
ip.expose_magic('wxactivate', wxactivate)
Now, after you run IPython -wthread
, you can call %wxactivate
and you will switch to the corresponding Python application!
(note that the reason why one has to run the call to appscript's activate()
in another process in not clear to me; it may have to do with some threading problem... any explanation would be appreciatated)
精彩评论