5

I'm running a script on python 3 that opens a URL using webbrowser.open() and immediately requires an input from the user. The problem is that the active window is now that of the browser instead of the python shell and an Alt-Tab or click is always required to provide the answer. You can imagine how frustrating it can be for thousands of images. The code is as simple as this:

 for rP in images:
     webbrowser.open(rP)
     decision = str(input('Is image '+str(rP)+' ok?')

I guess there are three ways of solving this but I can't seem to find an implementation for any of them. I've tried the 'autoraise' option in the webbrowser.open() command to no avail. I'm guessing that either solution will be so simple that I'll be banging my head afterwards.

So:
Solution #1: Have a command before the input line that makes the shell window active instead of the browser.
Solution #2: Open the webpage in the background thus never leaving the shell.
Solution #3: Give the shell window an "always on top" property.

Any ideas?

Arnab Nandy
  • 6,472
  • 5
  • 44
  • 50
dinos66
  • 686
  • 6
  • 15
  • To have both the prompt and the image on the screen, you could create a simple GUI: a text field for the answer and embedded pywebgtk or qt's webkit widget with the page. Or show a javascript message box with the question in the browser using selenium webdriver. – jfs Sep 18 '14 at 13:47
  • What operating system will this be running on? – Staven Sep 18 '14 at 14:15
  • 1
    To J.F.: I already have both of them on the screen by splitting up the windows, that's not the problem. The problem is that I can't give the shell the input without performing an intermeddiate action such as a click or alt-tab. To Staven: The OS will typically be Windows 7. – dinos66 Sep 19 '14 at 09:21
  • @dinos66: both solutions that I've suggested fix the focus issue too e.g., [look at my answers for the related question](http://stackoverflow.com/q/25733934/4279): no additional actions are required to start typing. – jfs Sep 21 '14 at 05:09
  • Have you tried `ipython`? It allows you to show images inline ([QtConsole](http://ipython.org/ipython-doc/stable/interactive/qtconsole.html) or in [web browser](http://nbviewer.ipython.org/github/ipython/ipython/blob/1.x/examples/notebooks/Part%205%20-%20Rich%20Display%20System.ipynb)). – jfs Sep 21 '14 at 08:31
  • @J.F.Sebastian First of all, thank you for your time. Regarding the solutions, I would prefer not to have more windows popping up (e.g. a gui) and not to have ipython as a dependency to anyone that uses my code. I'll look into the selenium webdriver solution as you suggested as it could be a way to solve this, although I still cannot believe there is no way of just making the shell window active. I mean, since I'm asking for an input, shouldn't the shell window become active automatically? – dinos66 Sep 22 '14 at 07:33
  • That is why I've suggested GUI instead: you have a *single* window -- *yours* window: you can put focus on whatever widget you like whenever you like. Here's how you could [show pictures in tkinter](https://gist.github.com/zed/8b05c3ea0302f0e2c14c). I don't know how to prevent the recent firefox from autoraising. How to still focus from other applications depends on windows manager. On Linux, `wmctrl` utility supports several of them. – jfs Sep 22 '14 at 08:28
  • I understand why you're suggesting a separate window, however, additional information and some automatic validation of images is also performed, so a new popup or an updating one is also a problem for me. Moreover, I need the browser instead of the tkinter illustrator as I might need to look at previously checked images which the new_tab in a browser provides in a nice manner instead of having new figures popup all over the place. You put it very nicely in the end of your last suggestion; I need to steal focus from all the other applications which I guess in windows is a pain, right? – dinos66 Sep 24 '14 at 09:03

2 Answers2

1

Windows

This was tested with Python 2.7.8, with a double AppActivate trick posted by partybuddha, and a sleep trick posted by eryksun:

from webbrowser import open as browse
from win32com.client import Dispatch
from win32gui import GetForegroundWindow
from win32process import GetWindowThreadProcessId
from time import sleep

images=['http://serverfault.com', 'http://stackoverflow.com']

for rP in images:
    _, pid = GetWindowThreadProcessId(GetForegroundWindow())
    browse(rP)
    sleep(1)
    shell = Dispatch("WScript.Shell")
    shell.AppActivate(pid)
    shell.AppActivate(pid)
    decision = raw_input('Is image ' + str(rP) + ' ok? ')

Without the 1 second sleep, the browser kept the focus, as if the AppActivate was happening too soon.

OS X

#!/usr/bin/env python
from webbrowser import open as browse
from subprocess import check_output

images=['http://serverfault.com', 'http://stackoverflow.com']

for rP in images:
     term = check_output(['/usr/bin/osascript', '-e',
         'copy path to frontmost application as text to stdout']).strip()
     browse(rP)
     check_output(['/usr/bin/osascript', '-e',
         'tell application "%s" to activate' % term])
     decision = raw_input('Is image ' + str(rP) + ' ok? ')

This code was tested with Python 2.7.5, so it may need tweaking to work with Python 3, but the core idea is to use osascript to get the frontmost application, and then activate it after opening the URL in the browser window.

Nick Russo
  • 1,522
  • 10
  • 13
  • The only solution I could find was by using tkinter and a series of always on top input buttons. This shouldn't be so hard, right? @Nick Russo: So you can actually gain focus on a window via a script in OS X? I don't have a mac, so I can't actually validate if it's a solution or not. – dinos66 Oct 07 '14 at 23:08
  • Yup, Applescript provides a way to address particular applications and tell them to do things. In this case, the code ends up telling Terminal to activate. – Nick Russo Oct 07 '14 at 23:11
  • Sorry Nick but I can't seem to get it to work. It runs fine for the first url but still won't return the focus to the shell after the second one. Tried increasing the delay to no avail. Also, it only works with python's command line and not with the Idle IDE. I am running python 3.3 however; maybe that's the problem. Thank you for your time! – dinos66 Oct 08 '14 at 15:52
0

If you use Selenium, focus automatically returns to the browser after .get().

Adam Michael Wood
  • 1,730
  • 16
  • 23