This article uses only the script of I want to prevent the speaker connected to Raspberry Pi (jessie) from getting stuck when the OS is restarted (Perl script) It is the content that I wrote it. Therefore, please be aware that there is nothing new except for scripts.
Please check I want to prevent the speaker connected to the Raspberry Pi (jessie) from becoming bon when the OS is restarted (Perl script).
Let's go now.
I will paste it for the time being. I will explain it below.
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
Let's take a closer look.
I imported sys and re to use standard input and regular expressions.
import sys
import re
Define a dictionary to hold each number. The name doesn't have to be HUB, but it happened to happen.
HUB = {}
The following is pre-compiled as a spell to turn regular expressions faster. From top to bottom, regular expressions for bus numbers, hub numbers, and port numbers. The regular expression itself is [at Perl](http://qiita.com/kouichirou/items/76dadc7cab6ef694fe18#%E5%AD%90%E3%82%B9%E3%82%AF%E3%83%AA%E3 It is exactly the same as% 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')
I won't explain the details, but each group (enclosed in parentheses) for back reference is included. For details, please refer to here.
It means that it will process line by line from the standard input.
for line in sys.stdin:
For the time being, [here](http://webdev.bulkitem.com/python%E3%81%A7%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B%E3% I also considered the method of reading the whole first like buffer = sys.stdin.readline.splitlines ()
as written around 82% 92% E8% AA% AD% E3% 82% 80). However, it seems that the speed was slow, so I stopped. (Even though, the difference was about 10% when the test data was inflated to about 200,000 lines (which is unlikely with lsusb -t), so either one is OK for practical use.)
First, check the value of HUB.
Find the read row in the precompiled object reHUB
.
tmp
is the object that contains the search results. It is used to back-reference the value acquired as a group at the time of search as tmp.group (1)
.
If there is an object in the search result (= if the regular expression matches), add a value to the HUB dictionary. As in the example, the key is the number of blank characters at the beginning of the corresponding line, and the value is the number following Port, which is acquired as a character string, converted to int type, and then added again as a character string with "." (Dot).
tmp = reHUB.search( line )
if tmp:
HUB[len(tmp.group(1))] = str(int(tmp.group(2))) + "."
continue
For example, the input string is as follows
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M
If it is, there are 4 digits of space.
HUB[len(" ")] = str(int("1")) + "."
That is, HUB [4] =" 1 "+". "
.
By the way, the reason why the number is set to int and str is that if the number part is 01
, the desired result to finally pass to unbind will be strange, for example, 01-01.01
. So I'm in trouble: severe :.
Therefore, even if it is the character string 01
, if you int it, it will become 1
, which is convenient later.
After assigning the value, continue and return to the head of for.
continue
If you do not include this, it will be very useless because it will search for subsequent rePort and reBUS. The total processing will be almost doubled. Even so, it takes about 1.2 seconds or 0.6 seconds for about 200,000 lines, so ... (Omitted below)
The processing content is almost the same as the above Hub, but the difference is that there is output processing.
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()
Match in the port search = Both BUS and HUB should already have values. Therefore, the value entered in the HUB dictionary is output as much as necessary. (As much as you need, because if there are long branches with many HUBs hanging in the middle, the HUBs will be as deep as the number of HUBs.
For example, suppose there is a long branch in the middle and the HUB dictionary is in the following state. (Dictionary keys shouldn't be sorted by nature, but for simplicity.)
['0':'1-' , '4':'2.' , '8':'1.' , '12':'3.' , '16':'2.' , '20':'1.' ]
#To value-Is attached to BUS,.HUB is attached.
Then take a few steps
['0':'1-' , '4':'3.' , '8':'3' , '12':'3.' , '16':'2.' , '20':'1.' ]
#To value-Is attached to BUS,.HUB is attached with, and Port is only the number without anything.
In that situation, it is correct to output 1-3.3
, but if you output all of them, it will be meaningless as 1-3.33.2.1.
.
So, for the HUB dictionary key, create a value from 0 for the required number of digits (up to 8 in the above case) with range, but since Python Range starts from 0, you have to +1.
for v in range(0,len(tmp.group(1))+1):
if HUB.has_key(v):
sys.stdout.write(HUB.get(v))
Also, since the key takes discrete values, it is checked with has_key
to prevent errors when there are no values.
Finally, it's BUS. However, it is almost the same as HUB. The difference is that the key is 0, which is a definite point. Since BUS is the highest level, there is no need to calculate it one by one.
tmp = reBUS.search( line )
if tmp:
HUB[0] = str(int(tmp.group(1))) + "-"
continue
The result of lsusb -t is at most a dozen lines, so in practice it doesn't matter which one you really use: sweat_smile :, I wonder how different the performance is, as mentioned above, the number of target lines is wasted. I tested it on the same Linux with more cases. It has been inflated to about 200,000 lines, but there is no point in mentioning the number of lines that are left over, so let's just worry about how much the same number of lines makes a difference.
When I measured the time of the Perl script (excerpt of only the corresponding process) several times with time, it was roughly
Perl
real 0m0.450s
user 0m0.433s
sys 0m0.031s
It's a sense of numbers. On the other hand, with Python,
Python
real 0m0.720s
user 0m0.710s
sys 0m0.019s
Feeling like. As for the value of user, Python is about 1.6 times. There is a considerable difference.
When the number of target lines is about a few actual lines
Perl
real 0m0.011s
user 0m0.004s
sys 0m0.006s
Python
real 0m0.021s
user 0m0.012s
sys 0m0.009s
I felt like saying. Hmm. I thought Perl was pretty heavy, but is it a bit faster than Python? (In this process, though.)
For the time being, I was concerned about the speed, so I thought about various Python algorithms as such.
As I have already explained above, it will be faster to think normally. After processing something, I will go to the next line without any extra processing. By the way, I think it would be better to do this in the Perl version as well, but I didn't want to change what I could write short, so I stopped thinking about it.
I also tried various things, but
--The number of BUS is absolutely small, so the last one is fine. ――As for HUB, I think it was better to bring it first because many HUBs were intentionally included in the inflated test data this time. ――So Port is in the middle. If there are few HUBs and there are a lot of ports, it may be better to change the order of HUBs and ports.
So I calmed down. If it's a university algorithm class, it would be evaluated by counting the number, but well, it's omitted: stuck_out_tongue :.
Since the processing in for is similar for BUS, HUB, and Port, I just wanted to make it a function. However, I had to change the regular expression of reBUS to make it a function, and it seems that the new reBUS was a drag, and it was about 10% slower. (In addition, the output part is incomplete because it was omitted in the following source, and it is cute that there is no "-" or "." When substituting into the HUB dictionary. It does not affect so much.)
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
I put the precompiled object in a dictionary called reS and for it.
It looks like it looks beautiful, it doesn't look like it. ..
The speed has almost doubled. It would be superfluous to check RE == rePort
every time after assigning to the new reBUS and reS and the HUB dictionary.
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
So, I tried various trials and errors, and it is the following source again. (Same as the first)
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
Recently, I was writing code only in languages such as PHP, Shell, and Perl, so I was a little annoyed by the politeness of Python as rumored. However, on the other hand, there was a recent awareness that I had to do type conversion properly, and that if I abbreviated it to a maniac so much, I wouldn't understand it for beginners, so I pinpointed the spine like when writing Java. I was able to work on it with the feeling (?)
I think I'm still using only the very basic features of Python, so I'll write about it again if I have something interesting to study in the future.
This Python script is [Child script for 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) does not hit lsusb -t internally, so if you want to implement it, chmod ugo + x [Python script full path]
Keep it
/usb/bin/lsusb -t | [Python script full path] > $UNBIND
Please describe in the parent script like.
Then.
Recommended Posts