Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#151 Le 26/01/2020, à 12:16

grim7reaper

Re : /* Topic des codeurs [9] */

Le truc de Windows je me demande si c’est pas plutôt un équivalent flock que flockfile, mais j’ai lu en diagonale.

Dernière modification par grim7reaper (Le 26/01/2020, à 12:17)

Hors ligne

#152 Le 26/01/2020, à 12:46

Dafyd

Re : /* Topic des codeurs [9] */

Sinon la méthode pour ne pas s’embêter avec ça serait de déléguer à un thread dédié la gestion des IO, et communiquer avec lui avec une file protégée par Mutex. Ce serait sûrement plus portable, et peut être aussi moins lourd à implémenter. Qu’en penses tu ?

Hors ligne

#153 Le 26/01/2020, à 14:21

Elzen

Re : /* Topic des codeurs [9] */

@grim : tes retours m'intéressent beaucoup, quand tu auras le temps smile

Dafyd a écrit :

Je vois que tu as vachement bossé sur l'architecture de Touhy. Très impressionnant je trouve. Tout comme l'utilisation d'une lib graphique ou d'une autre selon leur présence, le fallback sur différents systèmes audios, etc.. On voit la très grande force de Python pour cet usage... En C, ce serait galère, à grand coup de dlopen...

Oui, je doute fortement que j'aurais réussi à faire quelque chose d'aussi souple avec un langage autre que Python ; ou en tout cas ça aurait été pas mal plus compliqué à gérer.

Bon, après, il n'y a pas que Python dans l'affaire : comme mentionné, GTK me fait quelques soucis pour l'instant, je pense qu'il n'apprécie pas trop ma façon de faire, mais je vais bien finir par réussir à le domestiquer smile
À vue de nez, j'ai une source de segfault dans le module image (ça n'a pas l'air systématique, mais comme sencol fait pas mal de traitement d'image (pour les icônes liées au presse-papier ou aux capteurs de température, par exemple), le plantage finit par être quasi-systématique), et je n'arrive pas encore à identifier où précisément pour l'instant. Si quelqu'un veut aider à ça, n'hésitez surtout pas…

Tiens, du coup, avant de répondre aux questions de Dafyd (en fait, après, mais je reviens écrire là pour que la lecture du message soit plus cohérente que son écriture), un peu plus de détails sur ce fameux module images, donc le fonctionnement est (je trouve) théoriquement très élégant mais assez atroce à débuguer en pratique.

Le principe, c'est donc de transformer une chaîne de caractères comme celles présentées plus haut en une image. Par exemple, prenons cette chaîne-là :

#overlay(#small(t,r):#icon(add)):#flip(h):#icon(folder)

Dans cette chaîne,

  • « overlay » veut dire qu'on va prendre l'image qui est entre les grandes parenthèses, et la dessiner par dessus celle qui est après le « : » suivant.

  • « small(t,r) » veut dire que l'image qui suit sera affichée en plus petit, en haut (« t ») à droite (« r ») du cadre.

  • « icon(add) » veut dire qu'on va charger l'icône « add » (donc, conventionnellement, un + vert) du thème d'icônes actif.

  • « flip(h) » veut dire qu'on va inverser l'image horizontalement.

Et je vous passe le deuxième chargement d'icône, vous avez compris. L'image résultante sera donc l'icône de répertoire du thème actif, inversée horizontalement, sur laquelle aura été superposée l'icône « add » en haut à droite. Ça va, ça reste lisible smile

On a donc trois sortes d'opérations ici : celles qui génèrent une image à partir uniquement de leurs paramètres (« icon » ici, mais il y a aussi « file » pour lire un fichier (en pratique, c'est plein de fonctions différentes en fonction du type mime, mais simplifions :-°), « text » pour écrire du texte, « empty » pour faire une image vide, etc.), celles qui transforment une image donnée en autre chose (« flip » et « small » ici, j'ai aussi « negative », « rotate », « tint », etc.), et celles qui combinent plusieurs images (« overlay » ici, et pour le coup je n'en ai qu'une seule autre : « shape », qui trace la forme d'une image avec les couleurs de l'autre).
Chaque « chemin » d'image doit pouvoir être tracé pour une taille donnée (et quelques autres éléments de contexte, comme le thème d'icône actif, par exemple), et dans un format donné (par exemple, en GTK3, j'utilise le format GdkPixbuf pour afficher des icônes, mais par contre le format CairoContext pour tracer le fond des widgets graphiques). Une des difficultés étant bien sûr que les opérations faciles à faire ne sont pas les mêmes d'un format à l'autre (le « flip », une méthode de GdkPixbuf fait ça directement, par contre, je ne sais pas faire avec cairo, sauf à aller bidouiller les pixels à la main, ce que je n'ai pas eu envie de faire.)

Donc, pour faire ça, de base, j'ai deux modules : « plans.py » et « gears.py ». Comme leurs nom l'indique, le second contient les bouts de mécanismes à assembler, et le premier gère la façon dont les assembler smile En pratique, toutes les instructions qu'on peut trouver dans les chemins (overlay, flip, icon, etc. À quelques exceptions près comme small, qui sont en fait des combinaisons définies dans le fichier de config. En l'occurrence, small combine une instruction pour réduire la taille et une autre pour replacer la miniature à la bonne place) correspondent à une fonction (ou, vu qu'on est en Python, un callable, donc un objet qu'on peut appeler comme une fonction) présente dans le module « gears.py ».
Le module « plans.py » se charge donc de parser le chemin, étape par étape, de chercher à chaque fois le callable correspondant, puis l'appelle en lui passant son paramètre (ce qu'il y a entre les parenthèses, ou None s'il n'y avait pas de parenthèses), la suite du chemin, et le contexte. Cet appel ne fait aucun traitement d'images, pour l'instant, mais modifie le contexte si besoin, et renvoie un tuple de deux éléments :

  • Le premier est un tuple contenant les paramètres à appeler lors de l'appel réel à la fonction, ou None. Si c'est None, cette étape de la procédure ne nécessite aucun traitement d'image à proprement parler, ce n'était qu'une modif' de contexte (par exemple, « #theme(machin) » permet de sélectionner le thème d'icônes « machin » pour les chargements d'icônes dans la suite, mais ne fait rien en lui-même). Sinon, il faudra appeler la fonction de traitement d'image proprement dite, mais une fois qu'on aura la ou les images sur lesquelles le traitement doit s'effectuer. D'où le second élément du résultat,

  • un tuple contenant les chemins à appeler pour la suite. Si ce tuple est vide, on est sur une étape de création : on peut donc appeler la fonction de traitement d'image tout de suite, avec les paramètres sus-récupérés. S'il contient un seul élément, on va donc relancer la machine pour obtenir une image à partir de ce chemin, puis appeler la fonction de traitement sur cette image. S'il y en a deux, on va d'abord obtenir chacune de ces deux images séparément, puis ensuite on appelle la fonction avec les deux images.

Reste que, pour ça, il faut la fonction de traitement proprement dite, qui dépend du format de l'image à manipuler. En fait, chaque callable qui nécessite un traitement d'image contient un attribut _functs, qui est (en gros) un dictionnaire avec comme clef les formats manipulés en entrée et en sortie, et comme valeur la fonction spécifique à ces formats. L'appel global se fait avec le format de sortie désiré, puis, pour chaque étape, le programme regarde ce que je veux comme formats de sortie, ce que je sais gérer comme formats d'entrée, et demande à l'étape d'après de lui sortir une image qui sera du format le moins coûteux pour procéder à l'opération, en convertissant si besoin d'un format à l'autre au passage.
Tous les autres modules présents dans elzlibs/images/ et dans les différents _elzlibs_X/images (il n'y en a qu'en GTK 3, pour l'instant, mais je suppose que d'autres biblis graphiques ont des formats d'images spécifiques) servent ensuite à aller remplir ces différents _functs en fournissant des fonctions de traitement pour certains formats particuliers.

Tant que j'y suis, un peu plus de détails que plus haut. Actuellement, je gère :

  • Le format cairo.(Image)Surface, chez moi baptisé surface,

  • Les cairo.Context correspondants, format chez moi baptisé context, parce que pas mal d'opérations (de cairo ou de GTK) prennent ou renvoie un contexte, donc c'était plus simple de faire un format de plus que de convertir à chaque fois,

  • Le format PIL.Image, chez moi baptisé pillow,

  • Le format GdkPixbuf, chez moi baptisé pixbuf,

  • Un format baptisé matrix, qui est juste une liste de listes de listes d'entiers pour des opérations simples,

  • Un format baptisé stream, qui est juste le flux de bytes de l'image encodée en PNG dans un io.BytesIO.

Chaque format possède son module spécifique (sauf context et surface qui sont évidemment ensemble), qui contient toutes les fonctions de traitement que je sais faire sur le format en question. Les fonctions de conversion d'un format à l'autre ou de chargement d'un fichier depuis le disque sont placées dans le module du format de sortie.
Sachant qu'en plus de ça, j'ai un module spécial pour tracer des images d'un composant GTK en particulier (utilisé par exemple pour donner un look d'onglets aux boutons permettant de passer d'un bureau à l'autre sur les captures sus-mentionnées ; il faudra sans doute faire un équivalent pour changer de bibli graphique), et que le module streams.py gère aussi (enfin, gérera, parce que c'est tout cassé pour l'instant, mais je répare ça dès que j'ai débugué les segfaults) le fait qu'une application donnée puisse générer des images spécifiques pour une autre, à base de sockets.

L'__init__.py du module elzlibs/images fournit la liste des décorateurs (toute personne jetant un œil à mon code aura bien sûr remarqué que j'ai une certaine tendance à abuser des décorateurs) pour référencer tout ça, ainsi que deux fonctions de haut niveau : l'une pour charger un chemin donné à une taille (hauteur et largeur pouvant différer) donnée (qui peut déclencher des exceptions par exemple si on demande un traitement inconnu), l'autre pour charger une icône à une taille fixe (largeur et hauteur identiques) à partir d'une série de chemins (qui a priori ne déclenche aucune exception : si le premier chemin plante, ça tente le suivant, etc., jusqu'à balancer l'icône « image-broken » si ça n'est arrivé à rien).

Donc voilà, je trouve ça assez beau sur le papier, en pratique ça ne marche pas trop mal en dehors de ce souci de segfault, mais par contre, dans tout ça, pour identifier quel composant précisément est responsable d'une erreur qui n'a pas l'air systématique et qui fait planter le programme sans générer de stacktrace, ben… c'est coton, pour rester poli.

Dafyd a écrit :

-> Pourquoi ne pas utiliser les git submodules pour les elzlibs ? Chaque projet aurait son code, et un sous module pointant vers le dépôt d'elzlib. Ca pourrait te simplifier la vie en terme de déploiement par exemple...

En fait, j'utilise un truc assez proche de ça, mais (à mon humble avis, mais je connais sans doute trop mal submodules) plus souple.

Chaque appli a son dépôt, dans lequel j'intègre son code spécifique et les bouts de la bibliothèque commune dont j'ai besoin (et seulement eux : sencol n'a par exemple pas besoin de se trimballer l'entité média, il ne jouera pas de son. Pour show, dont on parlait plus haut, je n'ai pas besoin du daemon.py, vu que de toute façon ce sont des appels oneshots. Etc.), et j'ai un dépôt principal qui contient la liste des autres dépôts et quelques scripts de gestions du bazar.
Comme ça, le git de chaque appli est complètement autonome et ne contient que ce dont il a besoin (parce que, mine de rien, la elzlibs complète contient des tas de trucs pas forcément utiles), mais je peux facilement tout déployer au même endroit pour avoir les applis qui marchent dans un seul endroit. (Et les fichiers communs d'un dépôt à l'autre sont des liens physiques vers le même fichier, comme ça, les corrections apportées le sont partout en même temps. En temps normal (c'est-à-dire pas maintenant vu que je passe mon temps à casser des trucs pour finir la version repensée de la bibliothèque), les commit/push sur la elzlibs sont communs à tous les dépôts concernés).

Dafyd a écrit :

-> Pourquoi ne pas utiliser de venv python ? Ce serait pratique pour mettre en place un environnement de dev ou de prod contenant les libs dont tu as besoin, etc... Avec pip et un fichier requirements.txt.

Deux raisons à ça : d'abord, par confort personnel, je préfère n'avoir qu'un seul gestionnaire de paquets ou équivalent avec lequel me battre. Donc, chaque fois que c'est possible, je prends les modules pythons pour lesquels il existe un paquet deb dans les dépôts. Je ne suis même pas sûr d'avoir déjà utilisé pip, en fait…
Ensuite, le gros souci d'un projet comme Touhy, c'est que la liste des dépendances ne peut (sauf erreur de ma part, hein) pas se réduire à un requirements.txt : sencol a besoin par exemple de la commande externe acpi pour lire le niveau de la batterie, et je doute que pip puisse aller installer autre chose que des modules python. Pour l'interface graphique, pour l'instant, j'utilise encore quasi-essentiellement GTK, or depuis GTK 3, il n'y a plus des modules pythons directement comme c'était le cas avec PyGTK, mais une unique interface PyGI, et les dépendances sont ensuite à aller chercher côté GI, hors-python.
Donc bon, partant du principe que 1/ tout ce que j'utilise est dans les dépôts de Debian et d'Ubuntu, que 2/ l'installation automatique par pip serait a priori incomplète, et vu qu'en plus j'essaye justement de coder quelque chose qui s'adapte à ce qui va être présent ou pas sur la machine, je préfère lister les paquets deb dont j'ai eu besoin et laisser les gens installer ce qu'ils veulent à la main.

Sans doute que je me gourre, hein ; si quelqu'un veut contribuer en rajoutant ledit requirements.txt, ça me va smile

Dafyd a écrit :

Surtout pour la longévité du projet

Bah, je fais ça par phases, en fait. De temps en temps, je suis d'humeur à coder, alors je me fais des sessions où j'avance (ou où je casse) plein de trucs, et puis au bout d'un petit moment je laisse tomber et je fais autre chose, puis je m'y remet un peu plus tard. Sachant qu'en plus, c'est mon environnement principal, donc si je me rend compte à l'usage qu'un truc ne marche pas, ça m'embête et je dois le corriger, bah ça marche plutôt pas mal ^^

Hors ligne

#154 Le 26/01/2020, à 15:50

grim7reaper

Re : /* Topic des codeurs [9] */

@Dafyd : ouais, je ne sais pas ce que tu fais exactement mais j’étais en train de me demander si t’avais vraiment besoin d’I/O en parallèle.
En effet, avoir un thread dédié au I/O et les autres qui poussent leur résultats me semble plus simple/commun.

Hors ligne

#155 Le 26/01/2020, à 16:00

Dafyd

Re : /* Topic des codeurs [9] */

@grim Je suis en train d’écrire un bus de messagerie en réseau. Un DBus quoi. Ça n’a aucun intérêt, si ce n’est pratiquer le C, vu que je ne fais plus de dev au boulot. Ce sera articulé autour d’une architecture clients/serveur. Chaque client s’inscrit sur le bus dans des topics. Quand un client modifie un topic, tous les autres sont notifiés. Cote serveur donc, j’imagine un socket écoutant l’arrivée de nouveaux clients sur un port. Pour chaque client, le serveur instancie un thread qui ouvre un socket pour garder le lien avec le client. On a donc : un thread qui écoute les nouveaux clients. Un thread par client connecté. Un thread manipulant les fichiers de logs, ainsi que stdout et stderr. Un thread qui gère le bus en lui même (monitoring, création, suppression de topics, abonnement de clients, etc)...

Bon pour le moment, j’en suis très loin !

Hors ligne

#156 Le 27/01/2020, à 20:27

grim7reaper

Re : /* Topic des codeurs [9] */

Dafyd a écrit :

Pour chaque client, le serveur instancie un thread qui ouvre un socket pour garder le lien avec le client.

C’est peut-être un peu lourd ça, un thread par connexion.
Bon certes, tu devrais pas avoir des milliers de connexions, mais en général on préfère quand même les I/O non bloquantes pour ça (avec un thread qui fait du select/kpoll/…)

Hors ligne

#157 Le 27/01/2020, à 21:50

Elzen

Re : /* Topic des codeurs [9] */

Elzen a écrit :

Bon, après, il n'y a pas que Python dans l'affaire : comme mentionné, GTK me fait quelques soucis pour l'instant, je pense qu'il n'apprécie pas trop ma façon de faire, mais je vais bien finir par réussir à le domestiquer smile
À vue de nez, j'ai une source de segfault dans le module image (ça n'a pas l'air systématique, mais comme sencol fait pas mal de traitement d'image (pour les icônes liées au presse-papier ou aux capteurs de température, par exemple), le plantage finit par être quasi-systématique), et je n'arrive pas encore à identifier où précisément pour l'instant. Si quelqu'un veut aider à ça, n'hésitez surtout pas…

Bon, alors, je crois que j'ai réglé le bug, mais c'était assez chelou.

En fait, si tu n'as pas de boucle principale GTK démarrée, mon truc avait l'air de marcher nickel, d'où la difficulté à trouver l'origine précise du souci dans mes tests… par contre, si la boucle principale GTK tourne dans un thread et que j'appelle certaines fonctions de traitement d'images (je n'ai pas poussé jusqu'à identifier lesquelles précisément) depuis un autre, segfault immédiate sur mon jeu de test.

Du coup, j'ai « réglé » le souci en faisant en sorte que, systématiquement, toutes les fonctions de traitement d'image liées à GdkPixbuf soient appelées par le thread gérant la boucle principale GTK, en utilisant une queue.Queue pour ramener leur résultat dans le thread appelant. Et à vue de nez, plus de segfault ni d'autres erreurs bizarres à l'horizon.

Que les opérations sur les widgets et autres trucs vraiment graphiques aient besoin d'être dans le thread qui gère la boucle GTK, ça, ça se comprend (et c'était déjà pris en compte dans le reste de mon code), mais qu'il y ait ce genre de souci sur un traitement d'image qui a lieu en arrière-plan, ça m'étonne un brin.

grim7reaper a écrit :

C’est peut-être un peu lourd ça, un thread par connexion.

Tiens, d'ailleurs, l'un des inconvénient de la dernière version de ma bibliothèque qui utilise des socket dans tous les sens pour faire communiquer les applis entre elles, c'est que j'ouvre des tas de threads, maintenant… Et que je ne les referme pas toujours, d'ailleurs : si par exemple j'ai ouvert une socket DGRAM et que j'ai un thread qui attend des messages dessus, puis que pour une raison ou pour une autre, il m'arrive de devoir effacer le fichier, le thread reste en attente d'un message qui du coup n'arrivera plus jamais…
Toute suggestion pour améliorer ça sera la bienvenue.

Hors ligne

#158 Le 28/01/2020, à 06:33

Dafyd

Re : /* Topic des codeurs [9] */

@grim
Je vais me renseigner sur la méthode que tu mentionnes, je ne la connais pas. Est-ce portable ?

@Elzen
Concernant ton problème de thread GTK, j'avais déjà eu un soucis du même type. Que j'avais résolu plus ou moins de la même manière que toi me semble-t-il... Faudrait que je retrouve le code concerné au boulot. Après c'était en python 2.6 / gtk2. Je me demande si GTK n'utilise pas son contexte OpenGL pour faire des calculs, et un accès à ce contexte depuis un autre thread entraine une race condition et boum, segfault...

Pour ton soucis de libération de thread, peut-être pourrais-tu implémenter une classe Singleton qui fait office de Thread Manager. Tu instancies tes threads en passant par cette classe, qui garde un pointeur sur tous les threads instanciés et leur fichier socket. Elle scrute les fichiers socket avec fsnotify (https://github.com/seb-m/pyinotify), et en cas de suppression, libère le thread concerné.

Hors ligne

#159 Le 28/01/2020, à 16:11

Elzen

Re : /* Topic des codeurs [9] */

Dafyd a écrit :

Pour ton soucis de libération de thread, peut-être pourrais-tu implémenter une classe Singleton qui fait office de Thread Manager. Tu instancies tes threads en passant par cette classe, qui garde un pointeur sur tous les threads instanciés et leur fichier socket. Elle scrute les fichiers socket avec fsnotify (https://github.com/seb-m/pyinotify), et en cas de suppression, libère le thread concerné.

Ouaip, mais pour implémenter ça, il faudrait aussi que je sache comment proprement arrêter un thread qui est resté bloqué sur un socket.recv(), ce que j'ignore pour l'instant smile

D'ailleurs, il faut aussi que je regarde la partie inotify, pour le moment la « surveillance » des fichiers (pour repérer les modifs dans les fichiers de conf', par exemple) se fait avec un thread qui passe toutes les secondes vérifier leur date de dernière modification, ce qui n'est pas spécialement optimal (mais déjà, ça, c'est le même thread pour tous les fichiers, quand même, heureusement).

M'enfin, ce n'est urgentissime pour aucun de ces deux points : le truc tourne en l'état, et comme ce sont des opérations internes de la bibliothèque (dans un cas comme dans l'autre, le code côté programme se contente de définir la fonction qui sera appelée en cas de modif du fichier/de réception de message, en lui collant le décorateur qui va bien, et ne touche jamais directement aux threads/sockets/etc. Il est même possible que le code côté programme ne sache même pas si le fichier ressource utilisé est une socket ou un fichier plat, il pourra recevoir le contenu de la même façon), je peux continuer à coder le reste sans m'en préoccuper, ça ne cassera a priori rien le jour où je déciderai d'améliorer ça. Donc je préfère continuer à coder la partie programme et laisser ce types d'améliorations à quand je serai motivé pour ça et armé d'une bonne doc' smile
(Message subliminal : ou à quand quelqu'un trouvera ça trop moche et se décidera à contribuer pour améliorer ça :-°)


Sinon, une autre question qui ne va pas tarder à me poser un brin problème. En effet, (re-)coder les capteurs de sencol n'étant pas le truc le plus enthousiasmant du monde, je procrastine en avançant sur d'autres bouts du code, et je commence doucement à m'attaquer à Gemetic, donc le gestionnaire de bureau. Mais qui dit gestionnaire de bureau dit aussi affichage de l'image de fond. Et on touche là à une autre régression de GTK 3, en tout cas du côté du binding Python.

En PyGTK, pour récupérer l'image d'arrière-plan, je faisais à peu près comme ça :

from gtk import gdk
import wnck

screen = wnck.screeen_get_default()
xid = screen.get_background_pixmap()
if xid != 0L:
    disp = gdk.display_get_default()
    pixmap = gdk.pixmap_foreign_new_for_display(disp, xid)

La classe wnck.Screen fournissant même le signal adéquat pour me prévenir en cas de changement de ladite image de fond.

Le souci ici, c'est que, depuis GTK 3, la classe GdkPixmap a été supprimée, le truc utilise maintenant des CairoSurfaces à la place. Donc la méthode utilisée sur la dernière ligne n'existe plus. Du côté du module cairo pour Python, la méthode appropriée, « cairo_xlib_surface_create_for_bitmap », n'a pas de binding Python (je cite la doc' : « XlibSurface cannot be instantiated directly because Python interaction with Xlib would require open source Python bindings to Xlib which provided a C API. » Ce qui existe, soit dit en passant, vu que je m'en sers, mais ils n'ont pas l'air au courant. D'un autre côté, comme ils font encore référence à PyGTK, ce bout-là n'a pas du bouger depuis un moment).
Il y aurait bien une éventuelle troisième méthode qui pourrait fonctionner, « GdkX11.X11Window.foreign_new_for_display », sauf que celle-ci ne marche que s'il y a réellement une fenêtre derrière. Donc ça peut être utilisé pour faire une capture d'écran d'une autre fenêtre sans problème, mais pas pour récupérer l'image d'arrière-plan, qui, elle, n'est apparemment pas dans une fenêtre.

Quand j'avais encore une appli en PyGTK à côté, je pouvais ruser un peu en faisant en sorte que celle-ci récupère l'image de fond, et la fasse passer dans un presse-papier dédié pour que l'appli en GTK 3 la lise depuis là, vu qu'au moins, la communication par presses-papiers, ça marche bien. Mais comme je suis en train d'essayer autant que possible de tout passer à Python 3, je vais devoir changer de technique…

Le plus propre (et qui pourrait éventuellement avoir une utilité pour d'autres trucs plus tard) serait que (comme pour l'envoi de données vers le presse-papiers en GTK, où il manque aussi un binding Python 3), j'utilise la XLib en fallback. Ça demanderait que j'ai du code pour charger, depuis une xid donnée, une image au format d'image utilisé par cette dernière, puis que je sache convertir de ce format d'image-là vers n'importe lequel des formats que j'utilise dans mon module d'image (PIL.Image, GdkPixbuf, CairoSurface, ou un flux png). Tant qu'à faire, si je savais aussi faire une conversion dans l'autre sens, ça me permettrait de rajouter un format supporté à ma bibliothèque d'images, même si l'intérêt de la chose resterait assez limité.
Sauf que, comme souvent avec la XLib, ça a l'air compliqué, et je peine à trouver de la doc' compréhensible (voire de la doc' tout court). Donc, si quelqu'un a des pistes, je prends smile

(Et désolé Grim, j'te rajoute encore un pavé de plus à lire :-°)

Hors ligne

#160 Le 28/01/2020, à 18:33

Dafyd

Re : /* Topic des codeurs [9] */

Ben je vois que tu t’amuses avec GTK 3... a quand le passage à PyQT5 ? wink
Sinon tu as une doc ou quelque chose pour déployer touhy ? J’aimerais bien l’essayer, et pourquoi pas à l’occasion contribuer si bien sur je trouve le temps ...

Hors ligne

#161 Le 28/01/2020, à 20:33

Elzen

Re : /* Topic des codeurs [9] */

Ben, un des objectifs que j'avais en tête en commençant à casser un peu tout pour finir par arriver sur la structure que je vous ai décrit ci-dessus, c'est de permettre de changer de bibliothèque graphique sans trop que ça revienne à tout réécrire complètement.
Le truc chouette avec cette structure-là, c'est que (sous réserve que Qt5 fournisse un équivalent des GtkSocket/GtkPlug pour supporter le XEmbed, ce qui est probable mais je n'ai pas vérifié), ce sera tout à fait possible de commencer une version Qt5 par petits bouts, en gardant GTK en fallback pour tout ce qui n'est pas encore prêt.

Pour le déploiement, ça dépend ce que tu entends par là. Si c'est juste tester les applis une à une, il suffit de cloner leur dépôt, mais ça, je suppose que tu savais déjà smile
Pour cloner l'ensemble du projet d'un coup, comme je disais, il y a un dépôt « principal » qui contient les bibliothèques et quelques scripts en plus :
– check.py récupère ou met à jour les dépôts de toutes les autres applis d'un coup, en recréant les liens physiques entre les fichiers communs si besoin,
– build.py permet de créer à l'endroit indiqué un répertoire contenant trois répertoires bin/, lib/ et share/ contenant tout le nécessaire pour que tout marche correctement ensemble (il suffit donc d'ajouter le bin/ à $PATH et le lib/ à $PYTHONPATH).
– workenv.sh lance build.py vers un répertoire indiqué, et te lance un autre shell dans lequel tu as un Makefile et les bonnes variables d'environnement bien réglées. Je m'en sers pour bosser dans un tmpfs pendant que je casse des trucs sans toucher à la version « installée ».
A priori, c'est ce que tu veux. Il me reste un paquet de trucs à nettoyer dans ce dépôt principal, je tâche de faire ça d'ici à ce week-end et je vous poserai le lien là.

Par contre, si par « déploiement » tu veux dire faire en sorte d'avoir une session complète directement utilisable, ça n'existe pas pour l'instant, chez moi je passe par un ~/.xsession fait à la main (d'un autre côté, je n'ai pas d'outils pour tout dans Touhy. Typiquement, je n'ai pas poussé le vice jusqu'à développer mon propre gestionnaire de fenêtres, pour le moment j'utilise celui d'Xfce smile)

Hors ligne

#162 Le 28/01/2020, à 22:36

grim7reaper

Re : /* Topic des codeurs [9] */

Dafyd a écrit :

@grim
Je vais me renseigner sur la méthode que tu mentionnes, je ne la connais pas. Est-ce portable ?

Ni plus ni moins que les thread je dirais (encore que, depuis C11 y’a les threads dans la stdlib, mais bon la dernière fois que j’ai regardé Windows ils supportaient pas C99, donc C11…).
poll et select c’est du POSIX 2001 il me semble, mais après chaque OS à son mecanisme plus efficace (mais sur le même principe) : epoll pour Linux, kqueue pour BSD, …

Elzen a écrit :

(Et désolé Grim, j'te rajoute encore un pavé de plus à lire :-°)

tongue

J’avance, j’avance.

Voilà quelques remarques sur ce que j’ai lu pour l’instant :

Elzen a écrit :

J'envisagerais bien d'en ajouter un de plus qui permette d'afficher sur la sortie standard si le nombre de lignes est inférieur à la taille du terminal et de passer sur less dans le cas contraire, mais ça m'embête un peu parce que l'action attendue pour passer d'un fichier à l'autre ne serait du coup pas forcément toujours la même, donc pas glop niveau cohérence…

Comme "less --quit-if-one-screen"?


Elzen a écrit :

(Notez que, en vrai, vous pouvez mettre autant de - que vous voulez, zéro compris, pour les options, mon parseur commence par les virer).

Tu veux dire que je peux écrire "midote single"? Comment il sait que "single" c’est une option et non pas un nom de fichier à ajouter à la playlist?


Elzen a écrit :

Le daemon a besoin de python3-psutil pour lire les arguments des autres commandes (requis).

Si tu as seulement besoin de ça, il suffit pas de lire "/proc/PID/cmdline"?
Ça éviterai une dépendance pour si peu.

Hors ligne

#163 Le 28/01/2020, à 23:44

Elzen

Re : /* Topic des codeurs [9] */

grim7reaper a écrit :

Comme "less --quit-if-one-screen"?

Tiens, je ne connaissais pas…

Ceci dit, à vue de nez, ce n'est pas exactement ce que j'essayais de décrire, il faudra que j'y reréfléchisse pour préciser ça smile

grim7reaper a écrit :

Tu veux dire que je peux écrire "midote single"? Comment il sait que "single" c’est une option et non pas un nom de fichier à ajouter à la playlist?

C'est ça.

Le comportement par défaut, c'est que tout ce qui ressemble à « machin=truc » ou qui a été défini comme étant un paramètre n'attendant pas nécessairement de valeur (comme « single », donc) est considéré comme une option⁽¹⁾, et tout le reste comme possiblement un fichier (encore que je pourrais assez facilement restreindre à ce qui se trouve effectivement sur le disque, en fait, pour le coup, vu qu'un lecteur média va rarement créer des fichiers lui-même ^^)

C'est en partie pour ça que j'ai mis une option « then=FILE », qui permet d'échapper un nom de fichier qui aurait sinon été reconnu comme une option.

Après, il y a sans doute des tas de trucs à revoir dans ma gestion des options, je tâcherai de creuser le sujet un jour. En attendant, je mets des -- dans mon code (quand ça forke pour lancer le daemon, par exemple), et je n'en mets pas quand je lance des trucs moi-même dans le terminal.

grim7reaper a écrit :

Si tu as seulement besoin de ça, il suffit pas de lire "/proc/PID/cmdline"?
Ça éviterai une dépendance pour si peu.

Ah beh oui, ça a l'air tout à fait faisable, il faut juste que je trouve le caractère séparateur pour parser ça comme il faut. Je me suis davantage servi de psutil, à une époque, mais je crois qu'en l'état, je n'utilise que ça (je devais m'en servir, avant d'utiliser des sockets, pour chercher parmi la liste des processus actif si je trouvais un daemon en train de tourner ou pas, mais du coup ce bout-là a sauté).

D'un autre côté, /proc est spécifique au noyau Linux, non ? psutil est aussi compatible BSD, paraît-il, et j'ambitionne que Touhy puisse tourner au moins sous Debian GNU/kFreeBSD un jour (si ce truc existe encore quand je sortira une version présentable :-°) (mais d'un autre côté, la dernière fois que j'ai regardé, le paquet python(3)-psutil n'était pas porté dans les dépôts, donc de toute façon…)



(1) Edit : en fait, pour être un peu plus précis : j'ai un parseur d'arguments dont le comportement est le suivant :
– Virer tous les - au début pour voir et chercher s'il y a un = dans l'argument ou pas.
– S'il y en a un, on va considérer que c'est clef=valeur, et on regarde si on a des instructions pour parser la valeur en fonction de la clef (par exemple, c'est référencé que la valeur de --jump doit être un entier, donc si la clef est « jump », on parse la valeur comme entier), et on renvoie { clef, valeur }.
– S'il n'y en a pas, on regarde si cet argument correspond à une clef connue ou pas, et si oui, on prend sa valeur par défaut, et on renvoie aussi { clef, valeur }.
– Si ça ne correspond pas à une clef connu, mais que ça ressemble à « nomachin » ou « no-machin » où « machin » est une clef connue dont la valeur par défaut est un booléen, on renvoie { machin, non valeur }.
– Si aucun de ces cas n'a été rencontré, je reprends l'argument d'origine inchangé (avec ses - s'il y en avait), et on renvoie { None, argument }.
Et le programme doit ensuite se dépatouiller avec ça.

J'hésite à changer un peu ce comportement, par exemple en renvoyant { None, argument } en cas d'argument de la forme « machin=truc » si « machin » ne correspond à aucune clef connue… Toute suggestion bienvenue, pour ça aussi smile

Dernière modification par Elzen (Le 29/01/2020, à 00:14)

Hors ligne

#164 Le 29/01/2020, à 12:15

grim7reaper

Re : /* Topic des codeurs [9] */

Elzen a écrit :

C'est en partie pour ça que j'ai mis une option « then=FILE », qui permet d'échapper un nom de fichier qui aurait sinon été reconnu comme une option.

Ha, oui le --then sert à ça, bien vu.

Tiens d’ailleurs vu la description que tu en fais, j’ai l’impression que tu as fait un parser maison.
argparse te convenait pas?

Elzen a écrit :

Ah beh oui, ça a l'air tout à fait faisable, il faut juste que je trouve le caractère séparateur pour parser ça comme il faut.

un NUL ASCII, \0

man 5 proc a écrit :

/proc/[pid]/cmdline
       This read-only file holds the complete command line for the process, unless the process is a zombie.  In the latter case, there is nothing in this file: that is, a read on this file will return 0 characters.  The command-line arguments appear  in  this file as a set of strings separated by null bytes ('\0'), with a further null byte after the last string.

Elzen a écrit :

D'un autre côté, /proc est spécifique au noyau Linux, non ?

Oui et non, y’a énormément de trucs dans /proc sous Linux et y’a pas tout sur BSD, mais y’a quand même un minimum de compat’ il me semble (je viens de tester rapidos sur un FreeBSD et un DragonFly BSD là et j’ai bien cmdline)
Donc tant que les besoins reste basique comme ça, ça devrait aller.

Hors ligne

#165 Le 29/01/2020, à 19:53

Elzen

Re : /* Topic des codeurs [9] */

grim7reaper a écrit :

Tiens d’ailleurs vu la description que tu en fais, j’ai l’impression que tu as fait un parser maison.
argparse te convenait pas?

J'ai effectivement un parseur maison. Je me souviens que j'utilisais argparse fut une époque, je ne sais plus trop pourquoi j'ai changé (sans doute pour avoir plus souple/moins strict), mais disons que le gros avantage d'argparse, de mémoire, c'est de gérer facilement les combinaisons d'options courtes, du style « -argb » au lieu de « --alpha --red --green --blue ». Comme je n'ai pas l'intention d'utiliser des trucs de ce style-là, c'est typiquement un cas où refaire un parseur était aussi, voire plus simple que d'en utiliser un existant :-°

grim7reaper a écrit :

Oui et non, y’a énormément de trucs dans /proc sous Linux et y’a pas tout sur BSD, mais y’a quand même un minimum de compat’ il me semble (je viens de tester rapidos sur un FreeBSD et un DragonFly BSD là et j’ai bien cmdline)
Donc tant que les besoins reste basique comme ça, ça devrait aller.

Merci pour les précisions smile

Après vérif, je n'utilise pas que les arguments de la commande : j'utilise aussi le cwd (typiquement, quand tu demandes à midote d'ouvrir un fichier, il faut avoir son adresse à partir de l'endroit d'où lance la commande, pas à partir de là où tourne le daemon), et potentiellement aussi l'environnement. Mais à vue de nez, ça a l'air dans /proc aussi (je te laisse me confirmer la compatibilité si tu as du *BSD sous la main, ce qui n'est présentement pas mon cas), donc, a priori, pas spécialement de problème pour virer la dépendance.

Après, je me dis que parser systématiquement l'environnement, alors qu'en pratique je ne m'en sers jamais (du moins pour l'instant), ce n'est pas forcément très utile… Je vais peut-être, soit le virer, soit remplacer le dictionnaire par une fonction qui ne le parse et le renvoie que si on l'appelle. Après, je doute que ça change grand chose, mais bon.


Sinon, je viens de pousser quelques petites améliorations sur les fenêtres que je devais faire pour Gemetic (étant donné que la fenêtre du bureau reprend pas mal de code des fenêtres classiques, ça simplifie beaucoup ^^), et j'en ai profité pour faire en sorte que, si c'est la même appli qui gère la fenêtre et le composant qui va dedans, ça s'ajoute directement plutôt que de passer par XEmbed, c'est quand même plus simple comme ça. Et du coup j'en ai profité pour vérifier que le clignotement bizarre qui avait lieu au scroll venait vraisemblablement de ça, il n'a plus lieu maintenant.

Par contre, Midote continue de temps en temps de me planter entre les mains avec ce magnifique retour :

Gdk-Message: 19:20:37.820: midote: Fatal IO error 0 (Succès) on X server :0.0.

Je n'ai pas encore identifié d'où ça venait.

Hors ligne

#166 Le 30/01/2020, à 19:22

Dafyd

Re : /* Topic des codeurs [9] */

Accès concurrents à la socket de X11 ?

Hors ligne

#167 Le 31/01/2020, à 13:09

Elzen

Re : /* Topic des codeurs [9] */

Normalement, tout ce qui est graphique se fait dans le même thread… j'ai pu louper un truc, mais si c'est le cas, je n'ai pas encore trouvé où.
Mais j'aime toujours quand le message d'erreur est « Succès » big_smile


Bon, sinon, voilà, j'ai fini de nettoyer le dépôt principal. Donc si quelqu'un a envie de tester tout d'un coup, c'est là :

git clone git://fadrienn.irlnc.org/elzapps/touhy

Actuellement, ce dépôt permet de récupérer :
– show, qui est toujours dans le même état que lors du dernier post où on en a parlé⁽¹⁾,
– une très vague ébauche de clfb,
– sencol, qui actuellement sait fournir des entités pour la batterie, les capteurs de températures, les manettes et les presses-papiers,
– midote, qui à part cette erreur cryptique sus-mentionnée marche plutôt bien, même s'il reste des trucs à améliorer ça et là,
– un début de gemetic, encore pas mal incomplet pour l'instant, mais qui commence à ressembler à quelque chose si on fait sa conf' à la main.
Je relisterai les dépôts pour les autres applis quand elles seront dans un état vaguement utilisable smile

Dafyd, si tu veux éventuellement pouvoir contribuer, envoie-moi une clef SSh et dis-moi si tu préfères un compte sur mon serveur ou simplement un accès au compte guest smile

@Grim : du coup, modif faite. Je n'ai pas complètement retiré psutil : s'il est présent, il est utilisé (ça me paraît plus sûr au cas où), sinon, ça parse manuellement depuis /proc. À vue de nez, ça marche bien smile

(1) À un détail près : j'ai viré la partie Xlib de ce dépôt directement. Maintenant, pour lire le contenu du presse-papier via show, il faut soit que sencol soit lancé et fournisse les entités adéquates, soit installer tout au même endroit pour que show bénéficie de _elzlibs_gtk3 ou _elzlibs_xlib. Ça me paraissait plus simple comme ça.

Hors ligne

#168 Le 31/01/2020, à 21:04

grim7reaper

Re : /* Topic des codeurs [9] */

Bon j’ai fini de tout lire \o/

Sacré boulot, ça semble bien complet (et complexe par endroits ^^")

Elzen a écrit :

En même temps, c'est le seul bout de doc digne de ce nom existant sur ce que je fais actuellement, donc ce n'est carrément pas assez, mais bon.

Ça mériterait même de devenir une vraie doc, dans le repo Git et/ou dans la section Touhy de ton site smile

Elzen a écrit :

À vue de nez, j'ai une source de segfault dans le module image (ça n'a pas l'air systématique, mais comme sencol fait pas mal de traitement d'image (pour les icônes liées au presse-papier ou aux capteurs de température, par exemple), le plantage finit par être quasi-systématique), et je n'arrive pas encore à identifier où précisément pour l'instant. Si quelqu'un veut aider à ça, n'hésitez surtout pas…

Bah si t’a une image/script avec lequel t’arrives à reproduire fréquemment, je veux bien jeter un œil smile


Pour les submodules Git en effet, ça répond pas à ton besoin (vu que tu veux prendre des bouts de repo), pour ça faudrait que tu découpes le repo communs en repo plus petits.

Pour les venv Python, en effet ça ne gère que les deps Python. Ça peut éventuellement compiler des bouts de C mais ce n’est pas un package manager système (et ce n’est pas son but).

Le gros avantage c’est  que ça permet d’avoir plusieurs versions d’une même bibliothèque Python en parallèle.
Typiquement, je crois que tu développes sur Debian, donc tes versions packagées sont «vieilles» et si j’installe les paquets équivalent sur mon Archlinux y’a une chance non-nulle que ça ne fonctionne pas avec ton code sad
La solution c’est que je sache quelle version tu utilises, et que je l’installe dans un venv (comme ça, ça ne conflicte pas avec la version packagée par ma distrib’).
Du coup, un requirements.txt ça te serais pas forcément utile (vu que tu développes contre ce qui est packagé chez toi), mais ça peut aider les autres à savoir quoi installer (au lieu de deviner ta version Debian, chercher quelle version est packagée chez toi, …) rapidement smile

Elzen a écrit :

En fait, si tu n'as pas de boucle principale GTK démarrée, mon truc avait l'air de marcher nickel, d'où la difficulté à trouver l'origine précise du souci dans mes tests… par contre, si la boucle principale GTK tourne dans un thread et que j'appelle certaines fonctions de traitement d'images (je n'ai pas poussé jusqu'à identifier lesquelles précisément) depuis un autre, segfault immédiate sur mon jeu de test.

Ha, plus besoin d’aide donc.

Ouais, en général les bibliothèques graphiques aiment bien que leur tambouille restent dans leur thread principal.


Elzen a écrit :

Tiens, d'ailleurs, l'un des inconvénient de la dernière version de ma bibliothèque qui utilise des socket dans tous les sens pour faire communiquer les applis entre elles, c'est que j'ouvre des tas de threads, maintenant… Et que je ne les referme pas toujours, d'ailleurs : si par exemple j'ai ouvert une socket DGRAM et que j'ai un thread qui attend des messages dessus, puis que pour une raison ou pour une autre, il m'arrive de devoir effacer le fichier, le thread reste en attente d'un message qui du coup n'arrivera plus jamais…
Toute suggestion pour améliorer ça sera la bienvenue.

Bah le souci c’est que tu fermes pas la socket non?
IIRC, si tu as un processus bloqué en lecture sur une socket et que l’autre bout (qui écrit) appel close, bah celui qui attends des données va être notifié.

Ça marche comme ça en C il me semble (pas de raison que ça diffère en Python) :

man 3 recv a écrit :

RETURN VALUE
       Upon  successful  completion,  recv() shall return the length of the message in bytes. If no messages are available to be received and the peer has performed an orderly shutdown, recv() shall return 0. Otherwise, −1 shall be returned and errno set to indicate the error.

Elzen a écrit :

Sauf que, comme souvent avec la XLib, ça a l'air compliqué, et je peine à trouver de la doc' compréhensible (voire de la doc' tout court). Donc, si quelqu'un a des pistes, je prends smile

Le gros de la doc’ ce sont les pages de man, sinon y’a des vieux bouquins sur la Xlib (je dois avoir quelques un en PDF qui traîne sur mon disque).
Y’a ce site aussi (je me souviens l’avoir utilisé pendant mes TP de Xlib ^^).

Elzen a écrit :

c'est typiquement un cas où refaire un parseur était aussi, voire plus simple que d'en utiliser un existant :-°

Je peux comprendre si le truc supporte pas ce que tu veux faire.
Mais sinon c’est plus pratique d’utiliser un truc standard (surtout si tu veux des regards/contributions externes, ça diminue le coût d’entrée).

Elzen a écrit :

(je te laisse me confirmer la compatibilité si tu as du *BSD sous la main, ce qui n'est présentement pas mon cas)

Nope, y’a pas ça sous BSD.

FreeBSD :

% ls /proc/curproc/
cmdline ctl     dbregs  etype   file    fpregs  map     mem     note    notepg  osrel   regs    rlimit  status

DragonFly BSD :

% ls /proc/curproc/
cmdline ctl     dbregs  etype   file    fpregs  map     mem     note    notepg  regs    rlimit  status

Hors ligne

#169 Le 31/01/2020, à 22:32

Elzen

Re : /* Topic des codeurs [9] */

grim7reaper a écrit :

Bon j’ai fini de tout lire \o/

Sacré boulot, ça semble bien complet (et complexe par endroits ^^")

Bravo et merci big_smile

grim7reaper a écrit :

Ça mériterait même de devenir une vraie doc, dans le repo Git et/ou dans la section Touhy de ton site smile

Ouaip.

D'un autre côté, mon site entier mériterait que je me remette à taffer dessus, et le reste du serveur avec (il est toujours sous Jessie, je crois bien :-°)
Il faudra que je me trouve de la motiv' un jour. En attendant, je suis déjà content d'avoir écrit ça là, d'autant que l'essentiel des gens que c'est susceptible d'intéresser dans l'immédiat connaissent ce sujet, à ma connaissance.

grim7reaper a écrit :

Bah si t’a une image/script avec lequel t’arrives à reproduire fréquemment, je veux bien jeter un œil smile

Comme tu l'as remarqué plus bas, c'est a priori réglé pour ce souci-là. Par contre, si tu veux m'aider à trouver l'origine d'erreurs cryptiques, il y a le souci de midote sus-mentionné. Mais je n'ai pas encore identifié de moyen de le déclencher à coup sûr, donc bon.

grim7reaper a écrit :

Typiquement, je crois que tu développes sur Debian, donc tes versions packagées sont «vieilles» et si j’installe les paquets équivalent sur mon Archlinux y’a une chance non-nulle que ça ne fonctionne pas avec ton code sad

Déjà, je suis sous Sid, donc pas si vieilles que ça tongue

Et puis, a priori, les trucs que j'utilise sont plutôt stables… en tout cas, je ne me souviens pas de masse de trucs qui ont changé de fonctionnement depuis que je taffe là-dessus. Mais si tu repères des incompatibilités, signale-les moi, je tâcherai de commencer à tenir une liste à jour smile

grim7reaper a écrit :

Bah le souci c’est que tu fermes pas la socket non?
IIRC, si tu as un processus bloqué en lecture sur une socket et que l’autre bout (qui écrit) appel close, bah celui qui attends des données va être notifié.

Pour les SOCK_STREAM, oui, a priori, s'il y a un client connecté et que je ferme un bout, l'autre est notifié.

En revanche, pour les SOCK_DGRAM pour lesquels il n'y a pas de client à l'autre bout (il n'y a que le prog qui ouvre la socket qui attend des messages), et pour le thread qui attend la connexion de clients sur une SOCK_STREAM, soit il n'y a rien, soit je ne sais pas comment on vérifie ça.

grim7reaper a écrit :

Le gros de la doc’ ce sont les pages de man, sinon y’a des vieux bouquins sur la Xlib (je dois avoir quelques un en PDF qui traîne sur mon disque).
Y’a ce site aussi (je me souviens l’avoir utilisé pendant mes TP de Xlib ^^).

Merci, je m'y plongerai quand j'aurai le courage smile

grim7reaper a écrit :

Nope, y’a pas ça sous BSD.

Arf… pour l'environnement, je m'en fiche un peu, je ne m'en sers pas pour l'instant. Par contre, pour le cwd, tu sais s'il y a un autre moyen de le récupérer ?


Sinon, mon Gemetic commence vaguement à ressembler à ce à quoi il devrait, ce qui veut dire que je ne devrais plus trop trop tarder à virer ma version intermédiaire cassée (mais qui est encore en avance de quelques trucs utiles que je n'ai pas encore refait, comme la gestion du réseau par sencol) pour utiliser la nouvelle version comme environnement principale smile

Hors ligne

#170 Le 02/02/2020, à 20:23

grim7reaper

Re : /* Topic des codeurs [9] */

Elzen a écrit :

Par contre, si tu veux m'aider à trouver l'origine d'erreurs cryptiques, il y a le souci de midote sus-mentionné. Mais je n'ai pas encore identifié de moyen de le déclencher à coup sûr, donc bon.

Ouais, ce genre d’erreur est très chiant à comprendre, surtout si t’arrives pas à le reproduire hmm

Elzen a écrit :

Et puis, a priori, les trucs que j'utilise sont plutôt stables… en tout cas, je ne me souviens pas de masse de trucs qui ont changé de fonctionnement depuis que je taffe là-dessus. Mais si tu repères des incompatibilités, signale-les moi, je tâcherai de commencer à tenir une liste à jour smile

Ok, je te dirais si j’ai des soucis en testant.

Elzen a écrit :

En revanche, pour les SOCK_DGRAM pour lesquels il n'y a pas de client à l'autre bout (il n'y a que le prog qui ouvre la socket qui attend des messages), et pour le thread qui attend la connexion de clients sur une SOCK_STREAM, soit il n'y a rien, soit je ne sais pas comment on vérifie ça.

Ha oui sur de l’UDP c’est peut-être chiant.
Tu peux pas utiliser du TCP à la place?
Au pire, si tu es coincé avec l’UDP on pourrait imaginer que t’envoie un dernier message "goodbye" quand le thread émetteur se termine.

Elzen a écrit :

Arf… pour l'environnement, je m'en fiche un peu, je ne m'en sers pas pour l'instant. Par contre, pour le cwd, tu sais s'il y a un autre moyen de le récupérer ?

J’ai regardé vite fait et soit tu lances une commande via subprocess et tu parses la sortie…, soit c‘est relou (faut taper sur une fonction C depuis Python).
Vaut peut-être mieux rester avec psutils du coup…

Hors ligne

#171 Le 03/02/2020, à 18:58

Elzen

Re : /* Topic des codeurs [9] */

grim7reaper a écrit :

Ouais, ce genre d’erreur est très chiant à comprendre, surtout si t’arrives pas à le reproduire hmm

En l'occurrence, j'ai de bonnes raisons de penser que c'est un souci de thread. J'ai dû oublier le décorateur qui force à ce que ce soit dans le thread GTK sur une des fonctions quelque part. Je vais relire attentivement le code et essayer de trouver où…

J'ai trois autres soucis plus ou moins du même genre à résoudre avant que ça ne commence à devenir utilisable au quotidien :
– quand je laisse tourner sencol longtemps (avec tous les capteurs actuels actifs, je n'ai pas encore cherché lequel en particulier causait ça), ça finit au bout d'un temps aléatoire par me faire une stack overflow irrécupérable au chargement d'une image,
– des trucs dans gemetic semblent parfois avoir quelques petits soucis de mise à jour (par exemple, j'affiche une horloge dans un coin, il arrive qu'elle reste coincée sur une heure donnée alors que le reste continue de marcher correctement, de manière aléatoire),
– parfois, sans que je sache si c'est le même souci plus généralisé ou pas, gemetic s'arrête complètement de fonctionner, plus rien ne se met à jour graphiquement et les clics n'ont plus aucun effet.
Je n'ai encore investigué rien de tout ça, ça risque d'être dans mes prochains objectifs.

grim7reaper a écrit :

Ok, je te dirais si j’ai des soucis en testant.

Merci smile

grim7reaper a écrit :

Ha oui sur de l’UDP c’est peut-être chiant.
Tu peux pas utiliser du TCP à la place?
Au pire, si tu es coincé avec l’UDP on pourrait imaginer que t’envoie un dernier message "goodbye" quand le thread émetteur se termine.

Ouaip, mais d'un autre côté, je n'veux pas que n'importe quelle appli extérieure puisse arrêter le thread non plus smile

La version UDP me paraissait plus pratique à l'usage, avant de prendre en compte ce problème. Ça peut éventuellement être envisageable de changer. D'un autre côté, comme je le disais précédemment, ça, c'est de l'ordre des tâches de fond, je pourrai corriger ça plus tard sans que ça ne remette en cause la façon de fonctionner des programmes. Donc même s'il faudra que je m'occupe de ça à un moment ou à un autre, pour l'instant, j'ai tendance à procrastiner ça en m'occupant d'ajouter des fonctionnalités un peu partout, c'est plus motivant smile

D'ailleurs, à ce sujet, je viens d'ajouter le dépôt pour Catapult (c'est un chouette nom de lanceur, non ? tongue)

En l'état, ce nouveau logiciel affiche un « dock » gérable au clavier (fenêtre épinglée minimisée par défaut et qui se reminimise toute seule quand elle perd le focus ; mais qui peut aussi être affiché en permanence en l'embarquant dans un panel de Gemetic) permettant d'interagir avec les entités. En plus du fonctionnement classique, les icônes du dock peuvent afficher de petites popups dont le contenu est géré par les programmes correspondants, avec du XEmbed.
Chaque icône peut gérer plusieurs entités (on peut passer de l'une à l'autre en scrollant latéralement, ou avec les touches directionnelles au clavier), à condition qu'on interagisse avec toutes de la même manière. Catapult permet d'ailleurs, pour compléter, d'exposer plusieurs lanceurs comme des entités, et de lancer un programme si l'icône ne contient aucune entité pour l'instant. Du coup, j'ai déjà un midote hyper-bien intégré à l'environnement, et je compte faire pareil pour les autres applis ensuite smile

(Je prévois quelques fonctionnalités supplémentaires pour Catapult quand j'aurai la motiv' pour, notamment une meilleure gestion des fenêtres dans le dock, et quelques trucs chouettes en tâche de fond, du style, si je repère qu'un autre programme essaye d'accéder à une entité ou à un menu qui n'existe pas (c'est possible, non, avec inotify, de repérer les tentatives d'accès à un fichier ?), lancer automatiquement ledit programme en tâche de fond pour que ça marche de façon transparente. Mais bon, ce que j'ai fait là suffit pour l'instant pour un premier jet).

Quand j'aurai terminé les quelques trucs en cours, il faudra que je pense à faire une petite capture vidéo d'écran pour montrer un peu ce que ça donne en termes de possibilités, je pense que ça peut être assez classe.

grim7reaper a écrit :

Vaut peut-être mieux rester avec psutils du coup…

Ben, en l'état, je laisse tel que c'est : utiliser psutil s'il est installé, sinon faire « à la main » depuis /proc. Sous GNU/Linux, ça ne devrait pas poser de problème ; sous *BSD, ça va gêner pour midote, mais pas tant que ça⁽¹⁾, et comme les autres applis n'utilisent pas le cwd dans l'immédiat, ça tournera normalement (et il suffira d'installer psutil pour régler le fonctionnement de midote). Mais je verrai plus tard pour intégrer un contournement quand même, si c'est faisable. Mais ça risque d'attendre longtemps, du coup.

(1) elzlibs.daemon se contente de récupérer le cwd avec un « os.path.realpath(/proc/PID/cwd) » et de le passer à la fonction de lecture des arguments. C'est elle qui, ensuite, a la responsabilité d'os.path.join les arguments qui ont l'air d'être des fichiers s'il y a lieu. Du coup, tout ce que ça va faire en l'état, c'est que les chemins relatifs passés à midote par la ligne de commande seront lus au mauvais endroit. Le truc restera utilisable en lui filant des chemins absolus ou en utilisant l'outil graphique pour ajouter des morceaux à la playlist.

Hors ligne

#172 Le 04/02/2020, à 09:47

grim7reaper

Re : /* Topic des codeurs [9] */

Elzen a écrit :

– quand je laisse tourner sencol longtemps (avec tous les capteurs actuels actifs, je n'ai pas encore cherché lequel en particulier causait ça), ça finit au bout d'un temps aléatoire par me faire une stack overflow irrécupérable au chargement d'une image,

Y’a des stack overfow en Python oO?

Elzen a écrit :

– des trucs dans gemetic semblent parfois avoir quelques petits soucis de mise à jour (par exemple, j'affiche une horloge dans un coin, il arrive qu'elle reste coincée sur une heure donnée alors que le reste continue de marcher correctement, de manière aléatoire),
– parfois, sans que je sache si c'est le même souci plus généralisé ou pas, gemetic s'arrête complètement de fonctionner, plus rien ne se met à jour graphiquement et les clics n'ont plus aucun effet.

Ça ressemble à un thread qui se bloque ça, nan?

Elzen a écrit :

Ouaip, mais d'un autre côté, je n'veux pas que n'importe quelle appli extérieure puisse arrêter le thread non plus smile

Bah TCP ou UDP, c’est possible hein.
Sauf à faire communiquer tes process avec un protocole authentifié et chiffré, ça me semble définir à empêcher.
Après, je pense que c’est un faux problème, y’a pas de risque que ça arrive par erreur (et si c’est voulu, y’a d’autre moyen de tuer le thread/process de toutes façon tongue)

Elzen a écrit :

D'ailleurs, à ce sujet, je viens d'ajouter le dépôt pour Catapult (c'est un chouette nom de lanceur, non ? tongue)

Ouais, d’ailleur KDE3 avait Katapult tongue


Elzen a écrit :

(c'est possible, non, avec inotify, de repérer les tentatives d'accès à un fichier ?)

T’entends quoi par là?
Je pense pas que tu puisses être notifier sur un accès de fichier qui n’existe pas (si c’est ça la question).

Hors ligne

#173 Le 04/02/2020, à 17:20

Elzen

Re : /* Topic des codeurs [9] */

grim7reaper a écrit :

Y’a des stack overfow en Python oO?

Beh on dirait. D'un autre côté, il y a des langages où ce n'est pas possible ? Il y a des langages spécialisés pour la récursivité, mais il y a toujours une limite de taille de pile, non ?

grim7reaper a écrit :

Ça ressemble à un thread qui se bloque ça, nan?

Alors, dans le cas de l'horloge, pas du tout, c'est juste moi qui ai été con :-° (oublié de brancher un écouteur, ce qui faisait qu'elle n'était mise à jour qu'en cas de changement de bureau ^^")

Mais sinon, fort possible. J'ai fait quelques petites rectifs de code (notamment, en mettant un RLock automatique sur la fonction qui en avait besoin), et je n'ai pas revu d'erreurs de ce type depuis en cours de fonctionnement de programme (même s'il reste peut-être des GdkError bizarres au démarrage ?). Je laisse tourner un brin pour essayer de voir s'il y a d'autres ajustements à faire, et je commite ça…

grim7reaper a écrit :

Bah TCP ou UDP, c’est possible hein.
Sauf à faire communiquer tes process avec un protocole authentifié et chiffré, ça me semble définir à empêcher.
Après, je pense que c’est un faux problème, y’a pas de risque que ça arrive par erreur (et si c’est voulu, y’a d’autre moyen de tuer le thread/process de toutes façon tongue)

Oui, pas faux.

D'un autre côté, cette doc a l'air de dire que c'est mieux de laisser un thread attendre un message qui n'arrivera jamais plutôt que de chercher à interrompre ça, non ?

(Ce serait quand même globalement mieux si au lieu de dédier un thread à l'écoute de chaque socket pour cause d'attente bloquante, c'était faisable d'avoir un fonctionnement événementiel…)

grim7reaper a écrit :

Ouais, d’ailleur KDE3 avait Katapult tongue

Arf, mince. Je vais devoir renommer ça « trebuchet » pour désambiguer ? tongue

grim7reaper a écrit :

T’entends quoi par là?
Je pense pas que tu puisses être notifier sur un accès de fichier qui n’existe pas (si c’est ça la question).

Ben, il me semblait que c'était possible d'être notifié des accès à un fichier, donc j'espérais naïvement que ça marcherait aussi en cas de fichier inexistant, oui smile

Mais je vois d'autres façons de faire ça :
– Faire ce système de fichier FUSE spécifique, ce qui permettrait d'avoir ces notifs quand même en plus d'autres fonctions de confort (par exemple : au moment où un programme demande à lister les entités, vérifier que les processus qui gèrent les entités en question sont bien toujours actifs, et nettoyer si besoin, pour récupérer d'un truc qui a planté sans nettoyer, par exemple).
– Faire en sorte que les éventuels messages soient écrits dans un fichier plat s'il n'y a pas de socket à cet endroit-là, et Catapult se chargera dans ce cas de bouffer le message, de lancer le programme, et d'envoyer le message à la socket dès qu'elle est en place,
– Mettre une autre socket quelque part et reproduire le comportement du point précédent mais en envoyant les messages par là plutôt que de créer cradement le fichier,
– Faire plutôt ça avec un presse-papier dédié comme je faisais à une époque…

Bref, j'y réfléchirai en temps et en heure, ça ne presse pas.


Sinon, vu que la version actuelle devient à peu près utilisable, j'ai enfin remis la vieille version intermédiaire toute cassée que j'utilisais jusque là au placard et j'ai basculé vers la version actuelle que j'utilise désormais au quotidien. Ça me motivera à coder les trucs que je n'ai pas encore remis en place (du style, réglage du volume) quand j'essayerai de m'en servir et que ça ne marchera pas ^^

(Sinon, on a perdu Dafyd ?)

Hors ligne

#174 Le 04/02/2020, à 20:26

grim7reaper

Re : /* Topic des codeurs [9] */

Elzen a écrit :

Beh on dirait. D'un autre côté, il y a des langages où ce n'est pas possible ? Il y a des langages spécialisés pour la récursivité, mais il y a toujours une limite de taille de pile, non ?

Alors oui dans l’absolu c’est possible partout.
Après en Python je ne pense pas (sauf bug de l’interpréteur), car il fait beaucoup de chose sur le tas.
un StackOverflow c’est un crash violent comme une segfault quoi.
Autant j’ai déjà vu des MemoryError ou des RecursionError en Python (voire des segfault quand j’appelle du C depuis Python), autant une stack overflow pas encore (d’où ma surprise).

Elzen a écrit :

D'un autre côté, cette doc a l'air de dire que c'est mieux de laisser un thread attendre un message qui n'arrivera jamais plutôt que de chercher à interrompre ça, non ?

Il y a une différence entre interrompre un thread (ce qui me fait penser au "cancel", qui lui est souvent problématique) de l'extérieur et "le thread s'arrête de son plein grè car il a reçu un message 'salut'".
Après effectivement, si y'a des chances que tu reçoivent des données plus tard sur cette socket ça fait sens de le laisser poireauter.
Là je pensais qu’on était dans un cas où on nous parlera plus jamais.

Elzen a écrit :

Arf, mince. Je vais devoir renommer ça « trebuchet » pour désambiguer ? tongue

Ça serait pas déconnant tongue
J’ai découvert qu’il y avait une espèce de guerre trébuchet vs catapulte similaire à tab vs space ou Vim vs Emacs tongue
Genre ici ^^

Hors ligne

#175 Le 04/02/2020, à 22:23

Dafyd

Re : /* Topic des codeurs [9] */

Elzen a écrit :

(Sinon, on a perdu Dafyd ?)

Désolé j’ai pas beaucoup de temps libre en ce moment hmm

Hors ligne