Как проанализировать и выполнить поиск по списку взаимозависимых строк?

#python #list #search

#python #Список #Поиск

Вопрос:

Не уверен, как правильно сформулировать заголовок, но у меня есть этот список:

 Sink Input #1535
    Driver: protocol-native.c
    Owner Module: 10
    Client: 21932
    Sink: 0
    Sample Specification: s16le 2ch 44100Hz
    Channel Map: front-left,front-right
    Format: pcm, format.sample_format = ""s16le""  format.rate = "44100"  format.channels = "2"  format.channel_map = ""front-left,front-right""
    Corked: no
    Mute: no
    Volume: front-left: 32768 /  50% / -18.06 dB,   front-right: 32768 /  50% / -18.06 dB
            balance 0.00
    Buffer Latency: 0 usec
    Sink Latency: 23084 usec
    Resample method: n/a
    Properties:
        media.name = "Simple DirectMedia Layer"
        application.name = "ffplay"
  

с целой кучей других вещей, следующих.

Сначала мне нужно сопоставить на Input Sink# и записать следующие цифры до конца строки. Затем я должен выполнить поиск по application.name = и записать название программы, которое следует в кавычках. Затем поиск должен повториться для нескольких приемников и названий программ. Позже я планирую вернуть все входные номера приемников для данного имени приложения.

Текущий метод использует грубую силу и высокие системные ресурсы. Есть ли лучший метод, чем этот:

 def sink_list(prog,func):
    ''' Return list of Firefox or ffplay input sinks indices
    '''
    indices = []
    result = os.popen('pactl list short sink-inputs') 
                      .read().strip().splitlines()

    # TODO: We could be doing one os.popen and grabbing all sinks at once
    if len(result) == 0:
        print('sink_list() found no input sinks at all.' 
              '  Called by: ' func)
        return indices

    for line in result:
        sink = line.split('t')[0]
        app = os.popen('pactl list sink-inputs | grep "Sink Input #'   
                        sink   '" -A20 | grep application.name').read()
#        print("Searching for:",prog," in:",app," using input sink#:",sink)
        if prog in app:
            indices.append(sink)

#        print('indices',prog,':',indices)
    if len(indices) == 0:
        print("sink_list() found no input sink for: '"   prog   
              "' called by: " func)
        return indices
#    print("Found Input Sinks:", indices)
    return indices
  

Отвечать на комментарии

Был запрошен ввод:

     ''' Get old PID's and Input Sinks before ffplay '''
    old_pid = pid_list( "ffplay", "play_start()" )
    old_sink = sink_list( "ffplay", "play_start()" )
    self.have_ffplay_input_sink = False     # Each ffplay can have diff #

    # Launch ffplay in the background. CANNOT query result, it stops bkgrnd
    os.popen('ffplay -autoexit '   '"'   self.current_song_path   '"' 
                   ' -nodisp 2>'   TMP_CURR_SONG   ' amp;')

    ''' Get New PID's and Input Sinks for ffplay '''
    # Give time for `ffplay` to create pulseaudio sink.
    root.after(100)      # THIS IS UGLY, root.after is machine dependent!!!
    if not self.top2_is_active: return          # Play window closed?

    new_pid = pid_list("ffplay", "play_start()")
    new_sink = sink_list("ffplay", "play_start()")
    self.top2_ffplay_pid = list_diff(new_pid, old_pid, "play_start()")
    self.top2_ffplay_sink = list_diff(new_sink, old_sink, "play_start()")
  

Комментарии:

1. Взгляните на in оператор python. Он реализует ту часть grep , которая вам нужна.

2. @MadPhysicist Спасибо за этот совет. Я использую grep повсюду в моей последней программе на Python, и это моя вторая программа. Я программирую на bash всего четыре года.

3. Python, как правило, более универсален, чем bash. Вам понравится, как только вы к нему привыкнете

4. Можете ли вы показать пример вывода для нескольких приемников?

5. @MadPhysicist Если вам интересно, сегодня я ответил на свой собственный вопрос.

Ответ №1:

Я отвечу на свой собственный вопрос на случай, если это поможет другим.

Это функция, которую я написал, которая возвращает исходные требования плюс текущий объем:

 def sink_master():
    all_lines = []
    all_lines = os.popen('pactl list sink-inputs').read().splitlines()

    all_sinks = []
    in_sink = False
    in_volume = False
    for line in all_lines:
        if in_sink is False and "Sink Input #" in line:
            this_sink = line.split('#')[1]
            in_sink = True
            continue
        if in_sink is True and in_volume is False and "Volume:" in line:
            this_volume = line.split('/')[1]
            this_volume = this_volume.replace(' ','')
            this_volume = this_volume.replace('%','')
            in_volume = True
            continue
        if in_sink is True and in_volume is True and "tion.name =" in line:
            this_name = line.split('=')[1]
            this_name = this_name.replace(' ','')
            this_name = this_name.replace('"','')
            in_sink = False
            in_volume = False
            all_sinks.append(tuple((this_sink,this_volume,this_name)))
            continue

    print(all_sinks)
    return all_sinks
  

Когда вы запускаете его, он возвращает список кортежей:

 [('1828', '100', 'Firefox'), ('1891', '50', 'ffplay'), ('1907', '100', 'ffplay')]
  

Каждый кортеж содержит:

  1. Приемник ввода # используется pulseaudio (соблюдается ffplay )
  2. Текущий объем (с пробелами и % зачищен)
  3. Название приложения (с удаленными двойными кавычками " )