How to use `wx.ProgressDialog` with my own method? - python

How can I use the wx.ProgressDialog to time my method called imgSearch? The imgSearch method finds image files on the user's pc. How can I make the wx.ProgressDialog run while imgSearch is still running and display how long the imgSearch is taking?
Here's my code:
def onFind (self,event)# triggered by a button click
max = 80
dlg = wx.ProgressDialog("Progress dialog example","An informative message",parent=self, style = wx.PD_CAN_ABORT| wx.PD_APP_MODAL| wx.PD_ELAPSED_TIME| wx.PD_REMAINING_TIME)
keepGoing = True
count = 0
imageExtentions = ['*.jpg', '*.jpeg', '*.png', '*.tif', '*.tiff']
selectedDir = 'C:\\'
imgSearch.findImages(imageExtentions, selectedDir)# my method
while keepGoing and count < max:
count += 1
wx.MilliSleep(250)
if count >= max / 2:
(keepGoing, skip) = dlg.Update(count, "Half-time!")
else:
(keepGoing, skip) = dlg.Update(count)
dlg.Destroy()

The Problem
Your question is vague but after looking at your code I am going to guess that your problem is that imgSearch.findImages() completes before the dialog ever even opens. I'd appreciate if you could edit your question so I know if this is correct.
I see you are using code from this tutorial to show you how to use wx.ProgressDialog. Unfortunately, you are taking a rather naive approach to this. The purpose of that tutorial is to introduce readers to a wide range of built-in dialogs. As such, the wx.ProgressDialog example is a simple example simply to show you the methods, not to be used as an implementation.
Background Information
First, you need to know what multithreading is and how it works. Everything a computer does is broken down into a series of mathematical operations. The computer processor can only do one operation at a time. Therefore, the computer can only do one thing at a time. Now you might be thinking "well that isn't true. I'm listening to an MP3 while browsing the internet. That's at least two things". Well you're right and you're wrong. Imagine a chef. A chef can prepare many dishes at once but he can only pay attention to them one at a time. Therefore, he must switch between the dishes, performing some small task, until they are all complete. That's how a computer multitasks. Instead of "dishes", computers switch between "threads".
The Solution
Step 1: Threading
By default wxPython is only a single thread (this isn't exactly true, but just go with it). wxPython literally runs your code line-by-line such that one line must finish completely before the next line is run. Therefore, while imgSearch.findImages() is running no other code is executing and it must complete before the wx.ProgressDialog can even be created. The good news is that there are several ways to fix this. The bad news is that fixing this can become quite complicated. I'm not an expert but I suggest doing a search for "wxpython threading" and trying to find some tutorials. I found this tutorial but it is fairly old. The main point is that you will need to run imgSearch.findImages() in it's own thread so that it does not block the GUI.
Step 2: Metrics
So now, how do you make the wx.ProgressDialog reflect the actual status of imgSearch.findImages()? Well, that depends. You need to find some metric to help you measure how much has been done and how much more is left to do. In your code the metric is time because the progress is programmed to take 80 * 250ms = 20s. Time probably isn't what you want. You will need to decide what is best for your program but I will use the example of "number of folders" because it's easy to understand. I will count the total number of folders as well as the number of folders I have completely scanned. Now there's two ways to initialize your metric. You can calculate the max you need if the number is small or easy to calculate (such as time) or you can take a dynamic approach. In my case, calculating "number of folders" exactly would require almost as much time as the image search itself so dynamic is the best option. So, I would modify imgSearch.findImages() so that it keeps a count of the number of folders it has seen as well as the number of folders it has scanned (e.g. if my starting location has 3 folders I start with 3/0. I begin scanning the first folder which itself contains 2 more folders, so I now have 5/0. Every time I completely scan a folder I add 1 to the number of scanned folders, i.e. 5/1 after scanning one folder.). Knowing how many folders I have scanned and how many folders I have left to scan I can estimate my percentage completion using # of folders scanned / total # of folders. 1 / 5 = 0.20, therefore I estimate that I am 20% complete (note that if the next folder I scan contains 5 more folders then this number is automatically decreased to 10%. That is why I called 20% an estimate)
Step 3: Updating
So by now we should have imgSearch.findImages() in it's own thread and it should be able to estimate how far from completion it is. Now we need to update the wx.ProgresDialog. My favourite method for these types of problems is using the pubsub library. Basically, the imgSearch.findImages() thread must occasionally send a message which says how close to completion it is. Maybe at the end of each folder. Maybe ever three folders. It's up to you. Next, you will need to create a method in your main GUI's thread which can read these messages and update wx.ProgressDialog accordingly.
It's a lot of work but I wish you the best of luck.

Related

How to know the last launch time of a Python Program?

I am creating a Voice Assistant Program using Python and I wanna add a feature to it that shows the last time when the Assistant was used. Is there any method to do that? I am using tkinter for my GUI.
Often times, the obvious answer is the easiest/right one.
In this case, why not store the previous usages of the voice assistant?
It offers you a lot of benefits:
Being able to tell the user what was recognized previously
Allowing the user to spot previous (perhaps untowards) usage
Machine learning opportunities (previous utterances can be used as a reference for popular commands)
Repeat a command from the 'last x commands' list
In high level terms, the solution sounds like this:
on application close (maybe even on start) you should save the current timestamp (e.g. in a file), please check https://docs.python.org/3/library/datetime.html#datetime.datetime.now
then, on application start, try reading the previously saved timestamp.

Time trial version of a program

I want to create a trial version of a program for my customer. I want to give him/her some time to test the program (7 days in this case).
I have this command in the application (in *.py file):
if os.path.isfile('some_chars.txt') or datetime.now()<datetime.strptime('30-8-2015','%d-%m-%Y'):
# DO WHAT application HAS TO DO
else:
print 'TRIAL EXPIRED'
quit()
I'm curious whether is this approach enough for common customer or whether I have to change it. The thing is that the application has to find a file which name is, let's say, 'some_chars.txt'. If the file was found, the application works as it has to do, if not, it returns a text 'Trial version expired'.
So the main question is - is it enough for common customer? Can it be found somewhere or is it compiled to machine code so he would had to disassemble it?
EDIT: I forgot to mention very important thing, I'm using py2exe to make an executable file (main) with unnecessary files and folders.
Of course it has everything to do with the target (population) you're aiming: there are some cases when security is an offense (that involves lots of money so it's not our case);
Let's take an example:
Have a program that reads plain data from a file(registry,...); e.g. :the date (the program converts the date does a comparison and depending on the trial period close or lets the user go on)
Have everything from previous step, but the data is not in plain text, it is encrypted (e.g.: 1 is added to every char in the data so it is not immediately readable)
Use some well known encryption algorithms (would make the data unreadable to the user)
But, no matter the method you choose, it's just a matter of time til it will be broken.
A "hard to beat" way would be to have an existing server where the client could connect and "secretly talk" (I'm talking about a SSLed connecion anyway), even for trial period.
"Hiding the obvious info"(delivering a "compiled" .py script) is no longer the way (the most common Google search will point to a Python "decompiler")
Python is interpreted, so all they have to do is look at the source code to see time limiting section.
There are some options of turning a python script into an executable. I would try this and don't use any external files to set the date, keep it in the script.

Knowing how to time a task when building a progress bar

In my program a user uploads a csv file.
While the file is uploading & being processed by my app, I'd like to show a progress bar.
The problem is that this process isn't entirely under my control (I can't really tell how long it'll take for the file to finish loading & be processed, as this depends on the file content and the size).
What would be the correct approach for doing this? It's not like I have many steps and I could increment the progress bar every time a step happens.... It's basically waiting for a file to be loaded, I cannot determine the time for that!
Is this even possible?
Thanks in advance
You don't give much detail, so I'll explain what I think is happening and give some suggestions from my thought process.
You have some kind of app that has some kind of function/process that
is a black-box (i.e you can't see inside it or change it), this
black-box uploads a csv file to some server and returns control back to
your app when it's done. Since you can't see inside the black-box you
can't determine how much it has uploaded and thus can't create an
accurate progress bar.
Named Pipes:
If you're passing only the filename of the csv to the black-box, you might be able to create a named pipe (depending on your situation.) Since named pipes block after the buffer is full - until the receiver reads it, you could keep track of how much has been read and thus create an accurate progress bar.
So you would create a named pipe, pass the black-box its filename, and then read in from the csv - and write to the named pipe. How far you've read in - is your progress.
More Pythonic:
Since you tagged Python, if you're passing the csv as a file-like object, this activestate recipe could help.
Same kind of idea just for Python.
Conclusion: These are two possible solutions. I'm getting tired, and there may be many more - but I can't help more since you haven't given us much to work with.
To answer your question at an abstract level: you can't make accurate progress bars for black-box functions, after all they could have a sleep(random()) call in them for all you know.
There are ways around this that are implementation specific, the two ideas above are examples: the idea being you can make the black-box take a stream instead, and count the bytes as you pass them through.
Alternatively you can guess/approximate, a rough calculation of how many bytes are going in and a (previously calculated) average speed per byte would give you some kind of indication of when it would complete. You could even save how long each run took in your code and do the previous idea automatically getting better each time.

Python Progress Bar - Is Threading the Answer Here?

I've done some research on progress bars in Python, and a lot of the solutions seem to be based on work being divided into known, discrete chunks. I.e., iterating a known number of times and updating the progress bar with stdout every time a percentage point of the progress toward the end of the iterations is made.
My problem is a little less discrete. It involves walking a user directory that contains hundreds of sub-directories, gathering MP3 information, and entering it into a database. I could probably count the number of MP3 files in the directory before iteration and use that as a guideline for discrete chunks, but many of the mp3s may already be in the database, some of the files will take longer to read than others, errors will occur and have to be handled in some cases, etc. Besides, I'd like to know how to pull this off with non-discrete chunks for future reference. Here is the code for my directory-walk/database-update, if you're interested:
import mutagen
import sys
import os
import sqlite3 as lite
for root, dirs, files in os.walk(startDir):
for file in files:
if isMP3(file):
fullPath = os.path.join(root, file)
# Check if path already exists in DB, skip iteration if so
if unicode(fullPath, errors="replace") in pathDict:
continue
try:
audio = MP3(fullPath)
except mutagen.mp3.HeaderNotFoundError: # Invalid file/ID3 info
#TODO: log for user to look up what files were not visitable
continue
# Do database operations and error handling therein.
Is threading the best way to approach something like this? And if so, are there any good examples on how threading achieves this? I don't want a module for this because (a) it seems like something I should know how to do and (b) I'm developing for a dependency-lite situation.
If you don't know how many steps are in front of you, then how can you get a progress? That's the first thing. You have to count all of them before starting the job.
Now even if tasks differ in terms of needed time to finish you should not worry about that. Think about games. Sometimes when you see progress bars they seem to stop in one point and then jump very fast. This is exactly what's happening under the hood: some tasks take longer then others. But it's not a big deal ( unless the task is really long, like minutes maybe? ).
Of course you can use threads. It might be quite simple actually with Queue and ThreadPool. Run for example 20 threads and build a Queue of jobs. Your progress would then be number of items in Queue with initial length of Queue as a limit. This seems like a good design.

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.

Categories

Resources