Je veux empêcher le haut-parleur connecté au Raspberry Pi (jessie) d'être bonked lorsque le système d'exploitation est redémarré (script Python)

Préface

Cet article utilise uniquement le script de Je veux empêcher le haut-parleur connecté à Raspberry Pi (jessie) de devenir bon lorsque le système d'exploitation est redémarré (script Perl) en Python. Le contenu est que je l'ai écrit. Par conséquent, sachez qu'il n'y a rien de nouveau à part le script.

supposition

Veuillez cocher Je veux empêcher le haut-parleur connecté au Raspberry Pi (jessie) de devenir bon au redémarrage du système d'exploitation (script Perl).

Commentaire

Allons-y maintenant.

Script entier

Je vais le coller pour le moment. Je vais l'expliquer ci-dessous.

get_dac_port_num.py


#!/usr/bin/python
# coding: utf-8

import sys
import re

HUB = {}

reBUS  = re.compile(r'Bus (\d*)\.Port')
reHUB  = re.compile(r'^(\s*)\|__.*Port (\d*): .*Class=Hub')
rePort = re.compile(r'^(\s*)\|__.*Port (\d*): .*Driver=snd-usb-audio')

for line in sys.stdin:
        tmp = reHUB.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2))) + "."
                continue

        tmp = rePort.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2)))
                for v in range(0,len(tmp.group(1))+1):
                        if HUB.has_key(v):
                                sys.stdout.write(HUB.get(v))
                exit()

        tmp = reBUS.search( line )
        if tmp:
                HUB[0] = str(int(tmp.group(1))) + "-"
                continue

Regardons de plus près.

importer

J'ai importé sys et j'utilise des entrées standard et des expressions régulières.

import sys
import re

Définition variable

Définissez un dictionnaire pour contenir chaque numéro. Il n'est pas nécessaire que le nom soit HUB, mais c'est arrivé.

HUB = {}

Ce qui suit est pré-compilé sous forme de sort pour transformer les expressions régulières plus rapidement. De haut en bas, expressions régulières pour les numéros de bus, les numéros de hub et les numéros de port. L'expression régulière elle-même est [quand Perl](http://qiita.com/kouichirou/items/76dadc7cab6ef694fe18#%E5%AD%90%E3%82%B9%E3%82%AF%E3%83%AA%E3 C'est exactement la même chose que% 83% 97% E3% 83% 88).

reBUS  = re.compile(r'Bus (\d*)\.Port')
reHUB  = re.compile(r'^(\s*)\|__.*Port (\d*): .*Class=Hub')
rePort = re.compile(r'^(\s*)\|__.*Port (\d*): .*Driver=snd-usb-audio')

Je n'expliquerai pas les détails, mais chaque groupe (entre parenthèses) pour référence arrière est inclus. Pour plus de détails, veuillez consulter ici.

Routine principale

pour déclaration

Cela signifie qu'il traitera ligne par ligne à partir de l'entrée standard.

for line in sys.stdin:

Pour le moment, [ici](http://webdev.bulkitem.com/python%E3%81%A7%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B%E3% 82% 92% E8% AA% AD% E3% 82% 80) J'ai également considéré la méthode de lecture du tout en premier comme buffer = sys.stdin.readline.splitlines () Cependant, il semble que la vitesse était lente, alors je me suis arrêté. (Même si le résultat du remplissage des données de test à environ 200000 lignes (ce qui est peu probable avec lsusb -t) a montré une différence d'environ 10%, donc l'un ou l'autre convient pour une utilisation pratique.)

Contenu de pour 1 (HUB)

Commencez par vérifier la valeur de HUB. Trouvez la ligne de lecture dans l'objet précompilé reHUB. tmp est l'objet qui contient les résultats de la recherche. Il est utilisé pour référencer en arrière la valeur acquise en tant que groupe au moment de la recherche en tant que tmp.group (1). S'il y a un objet dans le résultat de la recherche (= si l'expression régulière correspond), une valeur est ajoutée au dictionnaire HUB. Comme dans l'exemple, la clé est le nombre de caractères vides au début de la ligne et la valeur est le nombre suivant Port, qui est acquis sous forme de chaîne de caractères, converti en type int, puis ajouté à nouveau sous forme de chaîne de caractères avec "." (Point).

        tmp = reHUB.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2))) + "."
                continue

Par exemple, la chaîne de caractères d'entrée est la suivante

    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M

Si c'est le cas, il y a 4 chiffres d'espace.

HUB[len("    ")] = str(int("1")) + "."

Autrement dit, HUB [4] =" 1 "+". ". À propos, la raison pour laquelle le nombre est défini sur int et str est que si la partie du nombre est «01», le résultat souhaité pour finalement passer pour délier sera étrange, par exemple, «01-01.01». Donc je suis en difficulté: grave:. Par conséquent, même s'il s'agit de la chaîne de caractères «01», si vous la saisissez, elle deviendra «1», ce qui est pratique plus tard.

Après avoir attribué la valeur, continuez et revenez à la tête de pour.

                continue

Si vous ne l'incluez pas, cela sera très inutile car il recherchera les rapports et reBUS suivants. Le traitement total sera presque doublé. Même ainsi, cela prend environ 1,2 seconde ou 0,6 seconde pour environ 200000 lignes, donc ... (Omis ci-dessous)

Contenu de pour 2 (Port)

Le contenu du traitement est presque le même que celui du Hub ci-dessus, mais la différence est qu'il y a un traitement de sortie.

        tmp = rePort.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2)))
                for v in range(0,len(tmp.group(1))+1):
                        if HUB.has_key(v):
                                sys.stdout.write(HUB.get(v))
                exit()

Correspondance dans la recherche de port = BUS et HUB doivent déjà avoir des valeurs. Par conséquent, la valeur entrée dans le dictionnaire HUB est sortie autant que nécessaire. (Autant que vous en avez besoin, car s'il y a une longue branche avec de nombreux HUB suspendus au milieu, le HUB sera aussi profond que le nombre de HUB.

Par exemple, supposons qu'il y ait une longue branche au milieu et que le dictionnaire HUB soit dans l'état suivant. (Les clés du dictionnaire ne doivent pas être triées par nature, mais par souci de simplicité.)

['0':'1-' , '4':'2.' , '8':'1.' , '12':'3.' , '16':'2.' , '20':'1.' ]
#Évaluer-Est attaché à BUS,.HUB est attaché.

Alors fais quelques pas

['0':'1-' , '4':'3.' , '8':'3' , '12':'3.' , '16':'2.' , '20':'1.' ]
#Évaluer-Est attaché à BUS,.HUB est attaché à, et Port est uniquement le numéro sans rien.

Dans un tel état, il est correct de sortir "1-3.3", mais si tous sont sortis, cela n'aura pas de sens comme "1-3.33.2.1.".

Donc, pour la clé du dictionnaire HUB, faites la valeur de 0 au nombre de chiffres requis (jusqu'à 8 dans le cas ci-dessus) avec range, mais comme la plage de Python semble commencer à 0, vous devez +1.

                for v in range(0,len(tmp.group(1))+1):
                        if HUB.has_key(v):
                                sys.stdout.write(HUB.get(v))

De plus, comme la clé prend des valeurs discrètes, elle est vérifiée avec has_key pour éviter les erreurs lorsqu'il n'y a pas de valeurs.

Contenu de pour 3 (BUS)

Enfin, c'est BUS. Cependant, c'est presque la même chose que HUB. La différence est que la clé est 0, ce qui est un point défini. BUS est le niveau le plus élevé, vous n'avez donc pas à le calculer un par un.

        tmp = reBUS.search( line )
        if tmp:
                HUB[0] = str(int(tmp.group(1))) + "-"
                continue

Fin d'explication

Histoire rapide de Perl et Python

Le résultat de lsusb -t est au plus une douzaine de lignes, donc en pratique, peu importe celle que vous utilisez vraiment: sueur_smile:, je me demande à quel point les performances sont différentes, comme mentionné ci-dessus, le nombre de lignes cibles est gaspillé. Je l'ai testé sur le même Linux avec l'augmentation des cas. Il a été gonflé à environ 200 000 lignes, mais il ne sert à rien de mentionner le nombre de lignes qui restent, alors préoccupons-nous simplement de la différence qu'il y a avec le même nombre de lignes.

Quand j'ai mesuré le temps du script Perl (version extrait du processus correspondant uniquement) plusieurs fois avec le temps, c'était à peu près

Perl


real    0m0.450s
user    0m0.433s
sys     0m0.031s

C'est un sentiment de chiffres. Par contre, avec Python,

Python


real    0m0.720s
user    0m0.710s
sys     0m0.019s

Se sentir comme. Quant à la valeur de l'utilisateur, Python est environ 1,6 fois. Il y a une différence considérable.

Lorsque le nombre de lignes cibles est d'environ quelques lignes réelles

Perl


real    0m0.011s
user    0m0.004s
sys     0m0.006s

Python


real    0m0.021s
user    0m0.012s
sys     0m0.009s

J'avais envie de dire. Hmm. Je pensais que Perl était assez lourd, mais est-ce un peu plus rapide que Python? (Dans ce processus, cependant.)

Histoire rapide uniquement en Python

Pour le moment, j'étais préoccupé par la vitesse, j'ai donc pensé à divers algorithmes Python en tant que tels.

Insérer Continuer → C'est plus rapide

Comme je l'ai déjà expliqué ci-dessus, il sera plus rapide de penser normalement. Après avoir traité quelque chose, je passerai à la ligne suivante sans aucun traitement supplémentaire. Au fait, je pense qu'il vaudrait mieux faire ça pour la version Perl aussi, mais je ne voulais pas changer ce que je pourrais écrire court, alors j'ai arrêté d'y penser.

Au lieu de l'ordre de BUS, HUB, Port, l'ordre est HUB, Port, BUS → C'est devenu plus rapide

J'ai aussi essayé diverses choses, mais

――Le nombre de BUS est absolument petit, donc le dernier convient. ――En ce qui concerne HUB, je pense qu'il était préférable de le mettre en premier car de nombreux HUB ont été intentionnellement inclus dans les données de test gonflées cette fois. ――Le port est donc au milieu. Il peut être préférable de changer l'ordre du HUB et du Port s'il y a peu de HUB et beaucoup de Ports.

Alors je me suis calmé. S'il s'agit d'une classe d'algorithme universitaire, elle serait évaluée en comptant le nombre, mais bon, elle est omise: stuck_out_tongue:.

Essayez d'utiliser la fonction → Il est tard

Comme le traitement de for est similaire pour BUS, HUB et Port, je voulais juste en faire une fonction. Cependant, j'ai dû changer l'expression régulière de reBUS pour en faire une fonction, et il semblait que le nouveau reBUS était un frein, et il était environ 10% plus lent. (De plus, la partie sortie est incomplète car elle a été omise dans la source suivante, et il est mignon qu'il n'y ait pas de "-" ou "." Lors de la substitution dans le dictionnaire HUB. Cela n'affecte pas tellement.)

reBUS  = re.compile(r'^\S*(\s*)Bus (\d*)\.Port')
#reBUS  = re.compile(r'Bus (\d*)\.Port')
reHUB  = re.compile(r'^(\s*)\|__.*Port (\d*): .*Class=Hub')
rePort = re.compile(r'^(\s*)\|__.*Port (\d*): .*Driver=snd-usb-audio')

def calc(re,line):
        tmp = re.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = int(tmp.group(2))
                return True
        else:
                return False

for line in sys.stdin:
        if calc(reHUB,line):
                continue

        if calc(rePort,line):
                print HUB
                exit()

        if calc(reBUS,line):
                continue

J'ai quitté la fonction, mais je vais l'écrire simplement → Il est tard

J'ai mis l'objet pré-compilé dans un dictionnaire appelé reS et pour cela. Ça a l'air magnifique, ça ne ressemble pas à ça. .. La vitesse a presque doublé. Il serait superflu de vérifier RE == rePort à chaque fois après l'affectation aux nouveaux reBUS et reS et au dictionnaire HUB.

reS = [reBUS , rePort , reHUB ]

for line in sys.stdin:
        for RE in reS:
                tmp = RE.search( line )
                if tmp:
                        HUB[len(tmp.group(1))] = int(tmp.group(2))
                        if RE == rePort:
                                print HUB
                                exit()
                        continue

La source entière à nouveau

Donc, j'ai essayé divers essais et erreurs, et c'est à nouveau la source suivante. (Identique au premier)

get_dac_port_num.py


#!/usr/bin/python
# coding: utf-8

import sys
import re

HUB = {}

reBUS  = re.compile(r'Bus (\d*)\.Port')
reHUB  = re.compile(r'^(\s*)\|__.*Port (\d*): .*Class=Hub')
rePort = re.compile(r'^(\s*)\|__.*Port (\d*): .*Driver=snd-usb-audio')

for line in sys.stdin:
        tmp = reHUB.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2))) + "."
                continue

        tmp = rePort.search( line )
        if tmp:
                HUB[len(tmp.group(1))] = str(int(tmp.group(2)))
                for v in range(0,len(tmp.group(1))+1):
                        if HUB.has_key(v):
                                sys.stdout.write(HUB.get(v))
                exit()

        tmp = reBUS.search( line )
        if tmp:
                HUB[0] = str(int(tmp.group(1))) + "-"
                continue

Impressions du premier Python

Récemment, j'écrivais du code uniquement dans des langages tels que PHP, Shell et Perl, donc j'étais un peu ennuyé par la politesse de Python selon la rumeur. Cependant, d'un autre côté, il y avait une prise de conscience récente que je devais faire une conversion de type correctement, et que si je l'abrégeais tellement en maniaque, je ne le comprendrais pas pour les débutants. J'ai pu travailler dessus avec le feeling (?)

Je pense que je n'utilise encore que les fonctionnalités très basiques de Python, alors j'écrirai à nouveau à ce sujet si j'ai quelque chose d'intéressant à étudier à l'avenir.

finalement

Ce script Python est [Child Script at Perl](http://qiita.com/kouichirou/items/76dadc7cab6ef694fe18#%E5%AD%90%E3%82%B9%E3%82%AF%E3%83] % AA% E3% 83% 97% E3% 83% 88) ne frappe pas lsusb -t en interne, donc si vous voulez l'implémenter, chmod ugo + x [chemin d'accès complet du script Python] Garde le

/usb/bin/lsusb -t | [Chemin complet du script Python] > $UNBIND

Veuillez décrire dans le script parent comme.

Puis.

Recommended Posts

Je veux empêcher le haut-parleur connecté au Raspberry Pi (jessie) d'être bonked lorsque le système d'exploitation est redémarré (script Python)
Je veux exécuter l'interface graphique Python au démarrage de Raspberry Pi
À propos de l'erreur que j'ai rencontrée en essayant d'utiliser Adafruit_DHT à partir de Python sur Raspberry Pi
[HyperledgerIroha] Requête avec la bibliothèque Python
Je voulais utiliser la bibliothèque Python de MATLAB
J'ai essayé d'utiliser la bibliothèque Python de Ruby avec PyCall
À propos de l'erreur que j'ai rencontrée en essayant d'utiliser Adafruit_DHT à partir de Python sur Raspberry Pi
J'ai créé une bibliothèque Python pour appeler l'API de LINE WORKS
Après avoir fait des recherches sur la bibliothèque Python, j'ai un peu compris egg.info.
Je veux empêcher le haut-parleur connecté au Raspberry Pi (jessie) d'être bonked lorsque le système d'exploitation est redémarré (script Python)
Je souhaite être informé de l'environnement de connexion lorsque RaspberryPi se connecte au réseau
Je veux initialiser si la valeur est vide (python)
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
Je veux utiliser jar de python
Je souhaite envoyer un e-mail depuis Gmail en utilisant Python.
[Python] Je veux gérer 7DaysToDie depuis Discord! 1/3
Je veux utiliser le solveur ceres de python
Ce que j'ai fait lors de la mise à jour de Python 2.6 vers 2.7
[Python] Je veux gérer 7DaysToDie depuis Discord! 2/3
Je veux créer du code C ++ à partir de code Python!
Je veux afficher la progression en Python!
[Python] J'ai créé un système pour introduire "la recette que je veux vraiment" depuis le site de recettes!
Quand j'ai essayé de faire une communication socket avec Raspberry Pi, le protocole était différent
Comment passer des arguments lors de l'appel d'un script python depuis Blender sur la ligne de commande
De la configuration du Raspberry Pi à l'installation de l'environnement Python
Je veux voir le nom de fichier de DataLoader
Comment utiliser Raspeye Relay Module Python
Je veux hériter de l'arrière avec la classe de données python
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux utiliser le jeu de données R avec python
Je veux faire quelque chose avec Python à la fin
[Selenium] Je souhaite afficher le navigateur en appuyant sur le pilote du système d'exploitation hôte à partir de WSL
Je souhaite générer une sortie lors de la conversion de la valeur du type (par exemple, datetime) qui n'est pas pris en charge lors de la sortie de json avec python
maya Python Je veux réparer à nouveau l'animation cuite.
Je veux démarrer beaucoup de processus à partir de python
Je souhaite calculer le temps d'arrêt autorisé à partir du taux de fonctionnement
[Python] Je souhaite utiliser l'option -h avec argparse
Je souhaite désactiver les interruptions sur le Raspberry Pi (≒ DI / EI)
Je souhaite envoyer un message de Python à LINE Bot
Je veux connaître la nature de Python et pip
Changer le message affiché lors de la connexion à Raspberry Pi
J'ai envoyé les données de Raspberry Pi à GCP (gratuit)
Écrivez un script dans Shell et Python pour vous avertir dans Slack lorsque le processus est terminé
Comment gérer le problème du déplacement du répertoire actuel lorsque Python est exécuté depuis Atom
Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées
J'ai essayé d'automatiser l'arrosage du pot avec Raspberry Pi
[Linux] Je souhaite connaître la date à laquelle l'utilisateur s'est connecté
Je veux sortir le début du mois prochain avec Python
Utilisez python sur Raspberry Pi 3 pour éclairer la LED (Hello World)
Je veux créer un système pour éviter d'oublier de serrer la clé 1
Remarques sur la connexion Bluetooth d'un smartphone / PC à Raspeye 4
Que faire lorsque le type de valeur est ambigu en Python?
[Python] Que faire en cas de violation de PEP8 lors du processus d'importation à partir du répertoire ajouté à sys.path
Je veux afficher le nombre de num_boost_round lorsque early_stopping est appliqué à l'aide du rappel XGBoost (non atteint)
Lisez les données du lecteur NFC connecté à Raspberry Pi 3 avec Python et envoyez-les à openFrameworks avec OSC