issue165:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue165:python [2021/01/30 12:35] – créée auntiee | issue165:python [2021/02/02 11:41] (Version actuelle) – auntiee | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | Welcome back to Python in the REAL World. | + | **Welcome back to Python in the REAL World. |
I’ve been really busy with a project for a friend and client. One of the things that his project requires is using GPIO pins on a single-board computer (not a Raspberry Pi) to monitor the position of a stepper motor. While doing research for this phase of the project, I needed to try to write and debug the code on my Linux desktop before testing the code on the single-board computer. Not very easy. One of the things that I need to do is handle keyboard input in an Event Oriented manner. | I’ve been really busy with a project for a friend and client. One of the things that his project requires is using GPIO pins on a single-board computer (not a Raspberry Pi) to monitor the position of a stepper motor. While doing research for this phase of the project, I needed to try to write and debug the code on my Linux desktop before testing the code on the single-board computer. Not very easy. One of the things that I need to do is handle keyboard input in an Event Oriented manner. | ||
- | One of the things that keeps me going to Tkinter and GUI programming is the ability to deal with events easily, without a tonne of extra programming and without a lot of overhead (outside of the GUI itself). Unfortunately, | + | One of the things that keeps me going to Tkinter and GUI programming is the ability to deal with events easily, without a tonne of extra programming and without a lot of overhead (outside of the GUI itself). Unfortunately, |
- | One thing that I needed was to capture keystrokes and deal with them without the need to press [Enter] all the time. Python doesn’t support this natively. I also needed to deal with multiple threads, and I haven’t “directly” messed with threads in a long while. Because of this, I decided to create a small demo program to get up to speed. After looking around on the Internet, I settled on a third party Python library to deal with the keyboard events. It’s called pynput. You can find the github repository at https:// | + | Ravi de vous revoir dans Python dans le monde réel. |
+ | |||
+ | J'ai été très occupé par un projet pour un ami et client. L'une des choses dont son projet a besoin est l' | ||
+ | |||
+ | L'une des choses qui me pousse à aller vers Tkinter et la programmation en interface graphique, c'est la possibilité de gérer les événements facilement, sans une tonne de programmation supplémentaire et sans beaucoup de choses en plus (en dehors de l' | ||
+ | |||
+ | |||
+ | **One thing that I needed was to capture keystrokes and deal with them without the need to press [Enter] all the time. Python doesn’t support this natively. I also needed to deal with multiple threads, and I haven’t “directly” messed with threads in a long while. Because of this, I decided to create a small demo program to get up to speed. After looking around on the Internet, I settled on a third party Python library to deal with the keyboard events. It’s called pynput. You can find the github repository at https:// | ||
Of course, since it’s a third-party package, you need to install it. You can easily do this via pip… | Of course, since it’s a third-party package, you need to install it. You can easily do this via pip… | ||
Ligne 12: | Ligne 19: | ||
or: | or: | ||
+ | |||
+ | pip3 install pynput** | ||
+ | |||
+ | Une chose dont j' | ||
+ | |||
+ | Bien sûr, comme il s'agit d'un paquet tiers, vous devez l' | ||
+ | |||
+ | pip install pynput | ||
+ | |||
+ | ou : | ||
pip3 install pynput | pip3 install pynput | ||
- | The documentation on pynput can be found at https:// | + | **The documentation on pynput can be found at https:// |
+ | |||
+ | Since pynput uses threading to do its magic, we should have at least a basic understanding of what threads are and how they work.** | ||
+ | |||
+ | La documentation sur pynput peut être consultée à l' | ||
- | Since pynput | + | Puisque |
- | Threads | + | **Threads |
There are two websites that I have found that really do a good job of threads: what they are, and how to use them. You can find them at https:// | There are two websites that I have found that really do a good job of threads: what they are, and how to use them. You can find them at https:// | ||
Ligne 25: | Ligne 46: | ||
I’ll try to break down the information that is provided on these two sites into simply a gross overview of threads. | I’ll try to break down the information that is provided on these two sites into simply a gross overview of threads. | ||
- | When you run a “normal” CLI (Command-Line Interface) program written in Python, it probably runs in only what’s called the main thread. All this means is that the execution of the program starts at the beginning and runs each statement, one at a time, until the end of the program, without trying to do anything else at the same time. A fairly good example that demonstrates the need for threads (in some things) is the time.sleep() function. When you call this function, all processing in the program stops until the specified amount of time is done. So if you call time.sleep(5), | + | When you run a “normal” CLI (Command-Line Interface) program written in Python, it probably runs in only what’s called the main thread. All this means is that the execution of the program starts at the beginning and runs each statement, one at a time, until the end of the program, without trying to do anything else at the same time. A fairly good example that demonstrates the need for threads (in some things) is the time.sleep() function. When you call this function, all processing in the program stops until the specified amount of time is done. So if you call time.sleep(5), |
- | In CLI programming, | + | Fils de traitement |
- | When pynput starts (the way we will use it), it creates a thread that continuously “listens” for any mouse or keyboard messages. Once it “hears” a keyboard message or mouse message, it responds by calling a function that we define. This function is called a callback function. In that function, we can handle whatever key was pressed or released, or, in the case of the mouse, a movement or button click. Once it has called the callback function, it goes back to listening until the next keyboard or mouse message. We really don’t have to understand the deep internals of pynput, only the callback functions and how to start the listening process. | + | J'ai trouvé deux sites Web qui sont vraiment bien sur les threads : ce qu'ils sont et comment les utiliser. Vous pouvez les trouver sur https://www.techbeamers.com/ |
- | To create the callback, we’ll first deal with the keypress callback. We’ll use his tutorial code (top right) for this. | + | Je vais essayer de décomposer les informations fournies sur ces deux sites en un simple aperçu général des threads. |
+ | |||
+ | Lorsque vous exécutez un programme CLI (Command-Line Interface) « normal » écrit en Python, il ne fonctionne probablement que dans ce que l'on appelle le fil principal. Tout ce que cela signifie est que l' | ||
+ | |||
+ | **In CLI programming, | ||
+ | |||
+ | When pynput starts (the way we will use it), it creates a thread that continuously “listens” for any mouse or keyboard messages. Once it “hears” a keyboard message or mouse message, it responds by calling a function that we define. This function is called a callback function. In that function, we can handle whatever key was pressed or released, or, in the case of the mouse, a movement or button click. Once it has called the callback function, it goes back to listening until the next keyboard or mouse message. We really don’t have to understand the deep internals of pynput, only the callback functions and how to start the listening process.** | ||
+ | |||
+ | Dans la programmation par CLI, vous pouvez contourner ce problème en utilisant un thread. Python et l' | ||
+ | |||
+ | Lorsque pynput démarre (comme nous l' | ||
+ | |||
+ | **To create the callback, we’ll first deal with the keypress callback. We’ll use his tutorial code (top right) for this. | ||
When a key is pressed on the keyboard, this function will be called. The key object is provided as a parameter. If we press the “a” key on the keyboard, the callback will print in the terminal… | When a key is pressed on the keyboard, this function will be called. The key object is provided as a parameter. If we press the “a” key on the keyboard, the callback will print in the terminal… | ||
Ligne 43: | Ligne 76: | ||
Or | Or | ||
- | special key Key.ctrl pressed | + | special key Key.ctrl pressed** |
- | This way, we can monitor for any type of keypress. We can also monitor for key-release as well. Sometimes, monitoring for the release of a key is a better option, since sometimes we can get multiple events when a key is pressed because the keyboard is internally dirty. Here is the author’s key-release callback function (bottom right). | + | Pour créer le rappel, nous allons d' |
+ | |||
+ | Lorsqu' | ||
+ | |||
+ | alphanumeric key a pressed # appuie sur touche alphanumérique a | ||
+ | |||
+ | Cependant, si nous appuyons sur une « touche spéciale » comme [Shift] ou [Ctrl], le rappel imprimera : | ||
+ | |||
+ | special key Key.shift pressed #appuie sur touche spéciale Touche.shift | ||
+ | |||
+ | ou | ||
+ | |||
+ | special key Key.ctrl pressed #appuie sur touche spéciale Key.ctrl | ||
+ | |||
+ | **This way, we can monitor for any type of keypress. We can also monitor for key-release as well. Sometimes, monitoring for the release of a key is a better option, since sometimes we can get multiple events when a key is pressed because the keyboard is internally dirty. Here is the author’s key-release callback function (bottom right). | ||
In this function, the callback is looking for just one thing. The [Esc] key, which will stop the listener process. | In this function, the callback is looking for just one thing. The [Esc] key, which will stop the listener process. | ||
Ligne 55: | Ligne 102: | ||
listener.join() | listener.join() | ||
- | Now, we’ll create our demo program that will contain the main thread, as well as two secondary threads and the listener thread. | + | Now, we’ll create our demo program that will contain the main thread, as well as two secondary threads and the listener thread.** |
+ | |||
+ | De cette façon, nous pouvons surveiller tout type d' | ||
+ | |||
+ | Dans cette fonction, le rappel ne cherche qu'une seule chose : la touche [Esc], qui arrête le processus d' | ||
+ | |||
+ | Pour démarrer listener (écouteur) de pynput dans la boucle principale, il suffit d' | ||
+ | |||
+ | with keyboard.Listener(on_press=on_press, | ||
+ | |||
+ | listener.join() | ||
+ | |||
+ | Maintenant, nous allons créer notre programme de démonstration qui contiendra le fil principal, ainsi que deux fils secondaires et le fil listener. | ||
- | The Code | + | **The Code |
The first thing we need to do, as always, is to import our libraries... | The first thing we need to do, as always, is to import our libraries... | ||
Ligne 67: | Ligne 126: | ||
from pynput import keyboard | from pynput import keyboard | ||
- | Next, we need to define our callback functions (next page, top right) for the listener. We’ve just discussed what they do. | + | Next, we need to define our callback functions (next page, top right) for the listener. We’ve just discussed what they do.** |
+ | |||
+ | Le code | ||
+ | |||
+ | La première chose à faire, comme toujours, est d' | ||
+ | |||
+ | import logging | ||
+ | import threading | ||
+ | import time | ||
+ | import datetime | ||
+ | from pynput import keyboard | ||
+ | |||
+ | Ensuite, nous devons définir nos fonctions de rappel (page suivante, en haut à droite) pour listener. Nous venons de discuter de ce qu' | ||
+ | |||
+ | **There will be two threads that each run in a continual loop, getting the current time, printing it, sleeping for a specified amount of time (each thread will have a different sleep time), and then doing it all over again. Since I’m using a simple while loop, the loop(s) run until the test condition is false. We set the condition to True before we start the loop. For example, in the first thread, we use a global variable called doloop1, which we set to True before the loop. The loop will continue to run until, and if, doloop1 becomes False. When it becomes False, the loop is exited, and the thread will end. In order to do this, I created a function called stop_threads() which sets the two global functions to False. This will be called after the [Esc] key is pressed to end the program. | ||
+ | |||
+ | def stop_threads(): | ||
+ | global doloop1, doloop2 | ||
+ | doloop1 = False | ||
+ | doloop2 = False** | ||
+ | |||
+ | Il y aura deux threads qui tourneront chacun en boucle continue, pour obtenir l' | ||
- | There will be two threads that each run in a continual loop, getting the current time, printing it, sleeping for a specified amount of time (each thread will have a different sleep time), and then doing it all over again. Since I’m using a simple while loop, the loop(s) run until the test condition is false. We set the condition to True before we start the loop. For example, in the first thread, we use a global variable called doloop1, which we set to True before the loop. The loop will continue to run until, and if, doloop1 becomes False. When it becomes False, the loop is exited, and the thread will end. In order to do this, I created a function called stop_threads() which sets the two global functions to False. This will be called after the [Esc] key is pressed to end the program. | ||
def stop_threads(): | def stop_threads(): | ||
Ligne 76: | Ligne 155: | ||
doloop2 = False | doloop2 = False | ||
- | Now (middle right) we define the first thread function. The idea behind this, as I said before, is to loop continuously, | + | **Now (middle right) we define the first thread function. The idea behind this, as I said before, is to loop continuously, |
Thread number two (bottom right) is almost exactly the same as thread number one, with the only difference is the sleep time for thread 2 is 10 seconds. | Thread number two (bottom right) is almost exactly the same as thread number one, with the only difference is the sleep time for thread 2 is 10 seconds. | ||
- | The main loop starts all of the threads and then sits idle until the listener thread notifies us that the [Esc] key has been pressed, then politely shuts down the two “worker” threads. | + | The main loop starts all of the threads and then sits idle until the listener thread notifies us that the [Esc] key has been pressed, then politely shuts down the two “worker” threads.** |
The next lines start the two time display threads and the keyboard listener. | The next lines start the two time display threads and the keyboard listener. | ||
Ligne 89: | Ligne 168: | ||
with keyboard.Listener(on_press=on_press, | with keyboard.Listener(on_press=on_press, | ||
- | listener.join() | + | listener.join()** |
+ | |||
+ | Maintenant (au milieu à droite), nous définissons la fonction du premier fil. Comme je l'ai déjà dit, l' | ||
- | At this point, when the listener.join() call is made, the program just waits. In a real program, you would normally have other things to do, but this is just a simple demo. Once the [Esc] key is released (remember that we monitor for that in the on_release() callback function), the rest of the code is run. | + | Le fil numéro 2 (en bas à droite) est presque exactement le même que le fil numéro 1, à la seule différence que le temps de sommeil du fil 2 est de 10 secondes. |
+ | |||
+ | La boucle principale démarre tous les fils et puis reste inactive jusqu' | ||
+ | |||
+ | Les lignes suivantes démarrent les deux fils d' | ||
+ | |||
+ | t1.start() | ||
+ | t2.start() | ||
+ | |||
+ | with keyboard.Listener(on_press=on_press, | ||
+ | |||
+ | listener.join() | ||
+ | |||
+ | **At this point, when the listener.join() call is made, the program just waits. In a real program, you would normally have other things to do, but this is just a simple demo. Once the [Esc] key is released (remember that we monitor for that in the on_release() callback function), the rest of the code is run. | ||
logging.info(" | logging.info(" | ||
Ligne 107: | Ligne 201: | ||
| | ||
- | When the program is run, we’ll get the following output in the terminal. | + | When the program is run, we’ll get the following output in the terminal.** |
+ | |||
+ | À ce stade, lorsque l' | ||
+ | |||
+ | logging.info(" | ||
+ | |||
+ | | ||
+ | |||
+ | logging.info(" | ||
+ | |||
+ | logging.info(" | ||
+ | |||
+ | Enfin, nous utilisons le code suivant comme point d' | ||
+ | |||
+ | if __name__ == " | ||
+ | |||
+ | | ||
+ | |||
+ | Lorsque le programme est exécuté, nous obtenons la sortie suivante dans le terminal : | ||
+ | |||
+ | **07:24:18: Main : before creating thread | ||
+ | 07:24:18: Main : before running thread | ||
+ | Press the <Esc> key to exit... | ||
+ | 07:24:18: Thread 1: starting | ||
+ | This thread shows the time every 5 seconds... | ||
+ | Thread 1 Time: 07:24:18 | ||
+ | 07:24:18: Thread 2: Starting | ||
+ | This thread shows the time every 10 seconds... | ||
+ | Thread 2 Time: 07:24:18 | ||
+ | Thread 1 Time: 07:24:23 | ||
+ | Thread 1 Time: 07:24:28 | ||
+ | Thread 2 Time: 07:24:28 | ||
+ | Thread 1 Time: 07:24:33 | ||
+ | Thread 1 Time: 07:24:38 | ||
+ | Thread 2 Time: 07:24:38 | ||
+ | ... | ||
+ | Thread 1 Time: 07:24:43 | ||
+ | Thread 1 Time: 07:24:48 | ||
+ | Thread 2 Time: 07:24:48 | ||
+ | Thread 1 Time: 07:24:53 | ||
+ | Thread 1 Time: 07:24:58 | ||
+ | Thread 2 Time: 07:24:58 | ||
+ | special key Key.esc pressed | ||
+ | 07:24:59: Main : wait for the thread to finish | ||
+ | 07:24:59: Main : all done | ||
+ | 07:24:59: Ending Program!** | ||
07:24:18: Main : before creating thread | 07:24:18: Main : before creating thread | ||
Ligne 136: | Ligne 275: | ||
07:24:59: Ending Program! | 07:24:59: Ending Program! | ||
- | That’s it. Now you have a light idea of how threads can be used, created, stopped, and how to capture keystrokes using pynput. | + | **That’s it. Now you have a light idea of how threads can be used, created, stopped, and how to capture keystrokes using pynput. |
I’ve put this month’s code up on my github repository at https:// | I’ve put this month’s code up on my github repository at https:// | ||
- | As always, until next time; stay safe, healthy, positive and creative! | + | As always, until next time; stay safe, healthy, positive and creative!** |
+ | |||
+ | C'est tout. Maintenant, vous avez une petite idée de la façon dont les fils peuvent être utilisés, créés, arrêtés, et comment capturer les frappes de clavier en utilisant pynput. | ||
+ | |||
+ | J'ai mis le code de ce mois-ci sur mon dépôt github à l' | ||
+ | |||
+ | Comme toujours, jusqu' | ||
issue165/python.1612006503.txt.gz · Dernière modification : 2021/01/30 12:35 de auntiee