Performing Pywinauto scripts from C# based application is slow - python

Updated on May 7th, history information is under line "***********************"
#Jakub Sowa I cannot add any comment below yours, I tried top_window and children(), it didn't seem to work to me. fox example
tp = cg.appConnect().top_window()
tp.children(title="finance", control_type="Button").draw_outline()
error occurs like-- AttributeError: 'list' object has no attribute 'draw_outline'
So would you give me a specific example to demonstrate how does it work in your case?
I've been doing pywinauto automation for a couple of months, but it runs slowly for some code, for example:
I click the button for confirmation in following code:
self.dlg = cg.appConnect().window(title="Hygine_Platform", control_type="Window")
self.regdlg = self.dlg.child_window(title ="registry", auto_id ="FormRegBalance", control_type="Window")
self.okbtn = self.regdlg.child_window(title="confirm",auto_id="btnOk",control_type="Button")
def clickConfSettle(self):
self.okbtn.click_input()
If I use clickConfSettle(), it takes at least five seconds to complete. Does anybody have the same problem, is there any solution for this? I've checked the structure of the controls, it is quite simple, only has 3 levels.

I've been using the library for a week or two only, but I've figured that if you get the Window Specification of the top window and it's children as soon as possible like so self.app.top_window().children() where app is the pywinauto.Application(backend='uia', allow_magic_lookup=False).connect(handle=self.handle) then your application should work much faster.
It takes the dict lookup away from you, however, you can still access items by indexes or iterate over them (which in my case was way faster than using child_window method). I'm not sure about the clicking part though as it may require some more time, but for the most part - all of the lookups in my program have gone under 1s after that change.

I'd like to answer with what I've tried so far. If I use var.children(attributes), index is still required. so it works with var.children(attributes)[], that runs faster than before.

Related

Is it possible to execute indented lines from another file in Python?

Say, I have two files demo.py
# demo.py
from pathlib import Path
for i in range(5):
exec(Path('another_file.txt').read_text())
and another_file.txt (note the indent)
print(i)
Is it possible to make python demo.py run?
N.B. This is useful when using Page (or wxformbuilder or pyqt's designer) to generate a GUI layout where skeletons of callback functioins are automatically generated. The skeletons will have to be modified, at the same time, each iteration overwrites the skeletons -- code snippets will have to be copied back. Anyway, you know what I am talking about if you have used any of Page or wxformbuilder or pyqt's designer.
You can solve the basic problem by removing the indent:
from pathlib import Path
import textwrap
for i in range(5):
exec(textwrap.dedent(Path('another_file.txt').read_text()))
There are still two rather major problems with this:
There are serious security implications here. You're running code without including it in your project. The idea that you can "worry about security and other issues later" will cause you pain at a later point. You'll see similar advice on this site with avoiding SQL injection. That later date may never come, and even if it does, there's a very real chance you won't remember or correctly identify all of the problems. It's absolutely better to avoid the problems in the first place.
Also, with dynamic code like this, you run the very real risk of running into a syntax error with a call stack that shows you nothing about where the code is from. It's not bad for simple cases like this, but as you add more and more complexity to a project like this, you'll likely find you're adding more support to help you debug issues you run into, rather than spending your time adding features.
And, combining these two problems can be fun. It's contrived, but if you changed the for loop to a while loop like this:
i = 0
while i < 5:
exec(textwrap.dedent(Path('another_file.txt').read_text()))
i += 1
And then modified the text file to be this:
print(i)
i += 1
It's trivial to understand why it's no longer operating the 5 times you expect, but as both "sides" of this project get more complex, figuring out the complex interplay between the elements will get much harder.
In short, don't use eval. Future you will thank past you for making your life easier.

How to suppress "Setting display..." in Abaqus scripting

I have many abaqus plugins that perform actions in Abaqus CAE through a scripting interface. For many actions after they are executed Abaqus performs some display refresh procedures that take some time. If the models are small and the script does not do too much it is alright. However, e.g. one of my scripts takes a part and replicates it in the assembly at the coordinates specified by user's CSV file. Sometimes there might be up to 2000 such replications. In this case it takes forever to complete the procedure and most of the time you only see "Setting display..."
Furthermore this "Setting display..." overwrites your scripts' progress (milestone) so it is difficult to see how far the script had advanced.
Is there any way to suspend this display updating behavior until the script finishes? Maybe there is a hack that you could redefine abaqus update function until the script is done or something because according to the manual the only thing you can do is to prevent the updating of the color scheme, but that does not help at all.
Any tips will be appreciated, thanks!
EDIT: To clarify I used folowing methods on a viewport object with no vain:
disableRefresh()
disableColorCodeUpdates()
What does the disableColorCodeUpdates() do is quite clear and the benefit is apparent when color coding is used in the model viewport. However, I see no difference between using and not using disableRefresh().
EDIT: Sorry for such a long wait, only now I had a chance to get back at abaqus. Here is a simple example script that takes a part and places it in assembly:
import random
modelName='Model-1'
partName='Part-1'
noInst=1000
i = 0
lists = []
for i in range(noInst):
lists.append([random.random()*10,random.random()*10,random.random()*10])
totalParts = len(lists)
session.Viewport(name='Viewport: 2', origin=(6.63750028610229,
20.7638893127441), width=335.746887207031, height=149.77685546875)
session.viewports['Viewport: 2'].makeCurrent()
session.viewports['Viewport: 2'].maximize()
session.viewports['Viewport: 1'].restore()
for n,l in enumerate(lists):
milestone('Replicating parts', 'parts', n+1, totalParts)
a = mdb.models[modelName].rootAssembly
p = mdb.models[modelName].parts[partName]
a.Instance(name='Random_'+'-'+str(n), part=p, dependent=ON)
a = mdb.models[modelName].rootAssembly
a.translate(instanceList=('Random_'+'-'+str(n), ), vector=(float(l[0]), float(l[1]), float(l[2])))
If I try to create viewport object without specifying displayed object. Viewport defaults to current displayed object in initial Viewport. I noticed if I change a module from amssembly to any other e.g. Part, I gain speed improvement, but it relies that the part is sufficiently empty. If I have model with parts that are large and complex it is still rather slow on "setting display.." also my milestone is overwritten by "setting display.." by any case.
I think I've seen this before in a similar situation, where I was creating elements one-by-one in a GUI CAE session. I could not figure out how to disable the screen refresh, and it was maddeningly slow. There were two workarounds:
1. Use an alternative command, if one exists, that creates many items at once. In my example above, instead of creating each new element one at a time using the Element method, I was able to generate an entire Part and the mesh at once with makePartFromNodesAndElements which was significantly faster. In your case, it might be possible to do something similar.
2. If you do not need an active GUI, run the script from the system shell: abaqus cae noGui=script.py. You can even pass arguments to the script from the command line interface.
Another (untested) possibility I just thought of is that you may be able to create and switch to a new viewport without specifying the displayed object. Then try your code and see if that speeds things up.

Need a way to retrieve the current playing song from Zune and Windows Media Player with Python

An Application of mine retrieves the current playing song from a multitude of music players. However, I'm having great trouble implementing Zune and Windows Media Player.
I've done a lot of googling on the subject, unfortunately it's only confusing me more and more.
What I would normally do for my other applications:
Iterate over all open windows every 4 seconds
Get the title of all windows
Check title for a pattern (Ie, " - Spotify ")
If it's there, adjust the title for output.
WMP Does not have the current playing song in the title.
Zune does, but it's rotating every few seconds between title, album and artist. Which is heavily unreliable to track with my current method, albeit possible.
Windows Media Player
I've also tried using the COM component for windows media player.
import win32com.client
wmp = win32com.client.gencache.EnsureDispatch('WMPlayer.OCX')
# some function I don't have here, it retrieves the current playing song
# and other data
The big problem with that it requires you to start WMP programmatically, which would be extremely user unfriendly
So, what have I found? This SO post redirects to WMP.dll. But as far as I've read, it has the same problem as the COM, you have to start it programmatically. If not, I would really like some directions on how to work with that dll in python.
There would be another a little less hacky solution, which is to write a plugin for WMP, let my users download that plugin and retrieve the data from that plugin. I'd rather not go there, since I have no experience with any of the C languages, nor do I feel like digging into plugin documentations for this.
Zune
A method would be to cycle through the three title states, determine which state it's currently at and find the position of the other two.
IE:
First 5 seconds the title is: Super_song
Next 5 seconds the title is: By Power_artist
Next 5 seconds the title is: Good_album (date)
So I could determine when the album title is by making a regex for the date (which is always there) and then find the title and artist by waiting a few seconds.
This is obviously not a great solution, since it'll take a while and it's not very reliable either, (what if the song name contains a date for example)
The next problem is that it's not consistent either, sometimes the title just stays Zune for minutes long. No idea why.
So, move on to the next method.
There's this application called ZuneNowPlaying. This "somehow" gets the current playing song from Zune and puts it in the registry, this thing does not work with my sloppy title method, since it changes the registry the instant the song changes. Immediately.
This is the solution I had used in the working version of my program, but many users reported that it simply didn't work, nothing happened. And I checked the program and it doesn't reliably change the registry all the time. I don't know why, I don't know how to fix it. Therefor, this solution is also -scrapped-.
Is the fact that it is using the name "MsnMsgrUIManager"#000000">
causing the zune software to send it information about which song is
playing? Is there a way to get this information without this kind of
hack?
That is found in the discussion of the Zune Now Playing application. The source is not available unfortunately, at least I can't find it. Anyone got more on this?
Third method I had heard of was once again, a dll. ZuneShell.dll it's called. I don't remember where I read about it, nor can I find it via google, since all results are "Is ZuneShell.dll a virus?".
Once again, I run into the problem that I wouldn't know how to work with this even IF I had documentation on it, heck, if it's even what I have been looking for.
Alternate directions to maybe look into
While browsing about this subject, I've seen people talking about retrieving data directly from GUI's. I'm not sure how legit, possible or even how correct my memory of it is, but if it's possible could someone redirect me to more on this?
Anything else, really.
I have working code in C++ to print the name of media currently playing in WMP. It's a simple console application (78 lines of code).
Steps:
1) implements a basic COM object implementing IUnknown, IOleClientSite, IServiceProvider and IWMPRemoteMediaServices. This is straightforward (sort of, your mileage may vary) using the ATL template CComObjectRootEx. The only methods needing (simple) code are IServiceProvider::QueryService and IWMPRemoteMediaServices::GetServiceType. All other methods may return E_NOTIMPL
2) Instantiate the "WMPlayer.OCX" COM object (in my case, via CoCreateInstance)
3) Retrieve from the object an IOleObject interface pointer via QueryInterface
4) Instanciate an object from the class seen in 1) (I use the CComObject<>::CreateInstance template)
5) Use the SetClientSite method from the interface you got at 3), passing a pointer to your OleClientSite implementation.
6) During the SetClientSite call, WMP will callback you: fisrt asking for an IServiceProvider interface pointer, second calling the QueryService method, asking for an IWMPRemoteMediaServices interface pointer. Return your implementation of IWMPRemoteMediaServices and, third, you will be called again via GetServiceType. You must then return "Remote". You are now connected to the WMP running instance
7) Query the COM object for an IWMPMedia interface pointer
8) If 7) didn't gave NULL, read the the IWMPMedia::name property.
9) DONE
All the above was tested with VS2010 / Windows Seven, and with WMP running (if there is no Media Player process running, just do nothing).
I don't know if yoy can/want to implement COM interface and object in Python. If you are interested by my C++ code, let me know. You could use that code in a C++ DLL, and then call it from python.
I just found a cool Python tool which can query all the controls of any program.
Simple, straightforward, and easy to read. It's here:
http://www.brunningonline.net/simon/blog/archives/winGuiAuto.py.html
With that you can get the info from the GUI.
You can also grab the loaded file list. It works for most media player.
You can get this information programmatically like this:
http://www.codeproject.com/Articles/18975/Listing-Used-Files
This is C++, but at that point you can wrap the native code.
This way you have to extract the ID3 tags yourself. Might worth the shot as it would be an universal solution.

How to periodically check for the current date from within a program?

I would like to write a tiny calendar-like application for someone as a birthday present (to be run on Ubuntu). All it should do is display a separate picture each day, so whenever it's invoked it should check the date and select the appropriate picture from the collection I would provide, but also, in case it just keeps running, it should switch to the next picture when the next day begins.
The date-checking on invocation isn't the problem; my question pertains to the second case: how can I have the program notice the beginning of the next day? My clumsy approach would be to make it check the current date at regular intervals and let it change the displayed picture once there was a change in date, but that strikes me as very roundabout and not particularly elegant.
In case any of you have got some idea of how I could accomplish this, please don't hesitate to reply. I would aim to write the application in either Perl or Python, so suggestions concerning those two languages would be most welcome, but any other suggestions would be appreciated as well.
Thanks a lot for your time!
The answer to this could be very system dependant. Controlling the time at which your program is executed is likely to be system dependant. On all *nix type systems, I would use cron. Assuming for a moment that you are using a *nix system, the answer then depends on what the program actually does.
If it only needs to select an image, then I would suggest that it not be run continuously, but terminates itself after selecting it, and is then run again the next day (there are a lot of tutorials on how to setup cron).
If, however, it has some form of UI and it is likely (read possible) to keep running for several days, then you can follow two approaches:
Create your program as it is, to poll periodically for the current time, and do a date delta comparison. Python timedelta objects could help here. This is pretty much your inelegant approach.
The other solution would be to send it a signal from cron when you do wish it to update. This process would mean that you would have to make it signal aware, and respond to something like USR1. The Python docs talk to this, but you can find many tutorials on the web. This approach also works quite nicely for daemonised apps.
I'm sure there are many other approaches too, but those are the ones that come to mind for a quickish and nastyish app.
Did you think about scheduling the invoke of your script?
For me, the best approach is this:
1.Have two options to run the script:
run_script
run_script --update
2.Schedule the update run in some task scheduler (for example Cron) to be executed daily.
3.When you would want to check the image for current day, simply run the script without update option.
If you would like me to extend any part of these, simply ask about it.

wxpython wx.AboutBox single instance

I'm still in the process of learning more about WxPython and I ran into a simple problem.
I like the wx.AboutBox class that manages how credits, licensing and other info is displayed to the user...and I'm not looking forward to building my own from scratch...although I can.
The problem here is that let's say I click on a button which brings up an AboutBox...seems like if you keep on clicking that exact button then multiple instances of the same AboutBox is brought up...and you end up multiple windows that just looks awkward in my opinion. As far as I've looked into it...there's no way to call the ShowModal() function that would allow you to get the ID of the close button in the aboutbox template and do some processing to make sure that only one instance is running.
I want to know how to stop this issue from happening...I want a single instance of wx.AboutBox and if it's not possible with this class due to it's nature/limitations then I'll have to consider building my own as a last resort.
Thanks
Creating your own AboutBox dialog is pretty easy. Here's an article that shows one way to do it: http://www.blog.pythonlibrary.org/2008/06/11/wxpython-creating-an-about-box/ or you could just use a GenericMessageDialog too. See the wxPython demo or http://www.blog.pythonlibrary.org/2010/07/10/the-dialogs-of-wxpython-part-2-of-2/
It seems like you haven't solved this problem yet. In wxPython, there's a class called "SingleInstanceChecker". I think this is what you're looking for.
http://wxpython.org/Phoenix/docs/html/SingleInstanceChecker.html

Categories

Resources