Possible to send commands to a wX GUI from a Python Script? - python

I have a wX application that I would like to control programmatically, from a Python Script. I tried to accomplish this by writing the following code:
Application = myApp()
myGUI= openGUI(Application)
This successfully opens an instance of my wX application, and I can then interact with this via its GUI, for instance by clicking Open File. However, I was hoping I could send commands by writing code like:
myGUI.OnFileOpen(myFile)
Unfortunately, inspecting "myGUI" in the debugger reveals the value of this variable to be "nothing". So I cannot access the methods of the running wX GUI via my proposed method.
If anyone could offer a suggestion for how to accomplish my goal, I would really appreciate it.

Related

AutoKey: Switch to last active application like Alt-Tab by using AutoKey

is it possible to send the alt+tab for switch to last window with AutoKey ?
i tried without success:
keyboard.send_keys("<alt>+<shift>+<tab>")
Or forward window:
keyboard.press_key('<alt>')
keyboard.press_key('<tab>')
keyboard.release_key('<tab>')
keyboard.release_key('<alt>')
Or backward window:
keyboard.press_key('<alt>')
keyboard.press_key('<shift>')
keyboard.press_key('<tab>')
keyboard.release_key('<tab>')
keyboard.release_key('<shift>')
keyboard.release_key('<alt>')
result: no error but only moves the tab count inside the editor.
TL;DR: Not directly with our API.
The AutoKey API talks directly to the current active window. So, sending events targeted at the desktop (DTE) will only work if the current active window recognizes them as such and either forwards them to the DTE or emulates what they do.
However, since AutoKey scripts are written in full Python 3, if you can figure out how to do it yourself in Python, AutoKey can run it for you. And, if some other solution is available, you can run it from within an AutoKey script using the subprocess module.
Autokey's Window class allows you to activate a window by name (via wmctrl), among other functionality. Something in that class may be what you're looking for.

Execute a keybind on a different application from python script

It's kind of hard to explain. Maybe the result is out there but I couldn't find it.
Simply put; I would like to run hotkeys on a program running on my desktop (Windows) via Python.
I have a 3rd party program that I have assigned certain hotkeys/keybindings to. For example when ctrl+Fn5 keys are pressed a certain command executes on that program.
What I want to do via Python scripts is to execute the mentioned hotkey (like ctrl+Fn5) on that program. (as if that program had focus on it and those keys were pressed)
I have been trying to do it via win32com.client. But the program itself doesn't allow that feature directly via its libraries. I also tried pywinauto but again it doesn't provide the libraries needed (tried analyzing it with other tools like swapy).
I have used catching hotkeys on python before. But they were for the Python application itself.
for example:
def keyPressEvent(self, e):
if e.modifiers() & Qt.ControlModifier and e.modifiers() & Qt.ShiftModifier and e.key() == Qt.Key_V:
# do somthing
What I need is to execute the hotkeys with the focus on the other program.
I looked into the os module to see if there was anything there that could help me but couldn't find anything.
Using pywinauto modules i got it to work. The trick was getting the focus on the program itself.
from pywinauto.application import Application
from pywinauto.keyboard import SendKeys
app = Application().connect(path='path_to_programs_exe_file')
app_dialog = app.top_window()
app_dialog.maximize()
app_dialog.set_focus()
SendKeys('^{F5}')

Python Pyside QT - Prevent Initialization of QT due to imports when running on CLI

So we have a rather large program written in Python using PySide/QT to get most of its GUI work done. We use Chaco to do some plotting.
This program also has a full CLI interface.
Every now and then a developer accidentally creates an import chain that causes our CLI runs to try and import something from PySide or Chaco. This causes our CLI runs to die with "cannot connect to x server" as either PySide or Chaco is trying to initialize X via QT.
Any tips on how to prevent this? Can we stub out and override some function that is doing this? Some flag we can pass along? Currently our prevention mechanism is track down the bad import and refactor.
So one semi-solution is to do the following. Essentially stub out the QApplication class and have it print a stack trace on init. This will break things but you will get a stack trace to do the first spot QtApplication tries to initialize.
_oldQtApplication = QtGui.QApplication
class BogusQApplication(QtGui.QApplication):
def __init__(self, *args):
import traceback
print traceback.print_stack()
_oldQtApplication.__init__(self, args)
QtGui.QApplication = BogusQApplication
A better solution would be to essentially stub the whole QtApplication class in such a way that users of it still work but essentially have a NullQtApplication. Unfortunately this appears to be a ton of work based on the usage of QtApplication in libraries like PySide of Chaco.
Rather than avoiding initialising Qt altogether, perhaps you could use QCoreApplication in your CLI applications. See the detailed description of QApplication in http://doc.qt.io/qt-5/qapplication.html for some example code you could adapt.
The good practice for such kind of pattern is to have a proper organisation of the code where the code using the user interface can't be imported when running on the CLI.
You can do that by designing your application in a pluggable way and only load the plugins needed by the CLI when running in CLI mode and the full set of plugins when running with the UI. We extensively use the Envisage framework to build pluggable application and solve those kind of problems. It requires a bit more upfront effort in designing your app.
For reference:
https://pypi.python.org/pypi/envisage
http://docs.enthought.com/envisage/
https://github.com/enthought/envisage

python, write a code to automatically execute an external program and use the method to execute the program's task

I want to run my external (.exe) program on window using python. in order to run a specific task of that program(the .exe) , i need to know the method and call in inside my test.py (my python file), how do i call a function in my python?
import subprocess
subprocess.call(['C:\\EnergyPlusV7-2-0\EP-Launch.exe', 'C:\\modelo_0001.idf'])
now i need to call a method through python to run a specific task on the external program(the .exe file), but how? can someone give me an example format? there s a button say 'simulate', i need to get the method for that button so that i can execute it through python!
You should try to use pywinauto for that: http://code.google.com/p/pywinauto/
Install it and read docs.
example:
from pywinauto import application
app = application.Application.start("C:\\EnergyPlusV7-2-0\\EP-Launch.exe")
# open dialog here with pywinauto (see docs), it's bound to interface can't help here
# press next button
Also look into SWAPY it will generate automation python code for pywinauto.
http://code.google.com/p/swapy/

Capturing stdout from an imported module in wxpython and sending it to a textctrl, without blocking the GUI

There are alot of very similar questions to this but I can't find one that applies specifically to what I'm trying to do.
I have a simulation (written in SimPy) that I'm writing a GUI for, the main output of the simulation is text - to the console from 'print' statements. Now, I thought the simplest way would be to create a seperate module GUI.py, and import my simulation program into it:
import osi_model
I want all the print statements to be captured by the GUI and appear inside a Textctrl, which there's countless examples of on here, along these lines:
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
<general frame initialisation stuff..>
redir=RedirectText(self.txtCtrl_1)
sys.stdout=redir
class RedirectText:
def __init__(self,aWxTextCtrl):
self.out=aWxTextCtrl
def write(self,string):
self.out.WriteText(string)
I am also starting my simulation from a 'Go' button:
def go_btn_click(self, event):
print 'GO'
self.RT = threading.Thread(target=osi_model.RunThis())
self.RT.start()
This all works fine, and the output from the simulation module is captured by the TextCtrl, except the GUI locks up and becomes unresponsive - I still need it to be accessible (at the very minimum to have a 'Stop' button). I'm not sure if this is a botched attempt at creating a new thread that I've done here, but I assume a new thread will be needed at some stage in this process.
People suggest using wx.CallAfter, but I'm not sure how to go about this considering the imported module doesn't know about wx, and also I can't realistically go through the entire simulation architecture and change all the print statements to wx.CallAfter, and any attempt to capture the shell from inside the imported simulation program leads to the program crashing.
Does anybody have any ideas about how I can best achieve this? So all I really need is for all console text to be captured by a TextCtrl while the GUI remains responsive, and all text is solely coming from an imported module.
(Also, secondary question regarding a Stop button - is it bad form to just kill the simulation thread?).
Thanks,
Duncan
I would suggest looking into this WX wiki article about long running tasks.
It specifically addresses the situation you're dealing with using a "start" button to being a long running process. Several different examples are given using different techniques like threads and idle handlers.
I think you would have to redirect stdout to a log file (or simple SQLite database?) and then use your thread to check the log file for updates which it would then pass along to the GUI using wx.CallAfter or similar. You might be able to use something like a socket server built in Python: http://wiki.wxpython.org/AsynchronousSockets. I think the wxPython Cookbook mentioned something about using an RPC server too (probably this one: http://docs.python.org/library/simplexmlrpcserver.html), but I don't remember the details.
You should also try asking on the official wxPython mailing list. They're very friendly over there.

Categories