{"id":14280,"url":"\/distributions\/14280\/click?bit=1&hash=c291fcfc43f419a1579e64e39746c746a194f7fcb7e35c6db5ddb6b8dad03dbe","title":" \u0423\u0441\u0442\u0440\u043e\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u0418\u0422 ","buttonText":"","imageUuid":""}

Вызов скриптов и библиотек на других языках

Обладая базовым уровнем знаний Python, можно выдать продукт, сопоставимый с готовыми решениями лидеров рынка. Количество готового кода постоянно растет, поэтому основное, что должен понять начинающий кодер, прежде чем накинуться на решения задачи и ее реализацию в коде - нужно потратить немного времени на поиск готовых решений. Другой вопрос, каково качество этого кода?

Вряд ли начинающий кодер будет допущен до какой-то уникальной задачи, следовательно, вероятность найти готовое или похожее решение совсем ненулевая. Но здесь тебя могут подстерегать «грабли» — решение может быть на другом языке.

Получается, готовое решение любой задачи можно загуглить?

И что тогда? Учить 100500 языков?

Python позволяет осуществлять вызовы скриптов и библиотек на других языках. И для этого не обязательно их учить, главное – понимать, что подавать на вход и что ты получишь на выходе. Как раз похожий кейс возник и у нас.

И в чем заключался кейс?

При решении задачи по анализу диалогов клиентов и брокеров, для получения информации по полу и возрасту клиента, нужно было получить спектральные и частотные результаты обработки аудио файлов в конкретном виде. Усиленное гугление выдало, что результаты в данном виде могут быть получены после обработки аудио с помощью функции specan языка R. Прямого аналога данной функции в Python опознано не было, возможные варианты получения аналогичных данных с помощью Фурье навевали тоску. Дальнейший поиск выдал решение — запускаем функции R напрямую из Python. Способов такого запуска существует несколько: можно использовать специализированные библиотеки или осуществить исполнение скриптов с помощью командной строки (command line tools) + промежуточное хранение файлов на диске (filling air gap).

И как конкретно был решен вопрос?

Мы выбрали command line tools, так как для этого не требовалась установка дополнительных модулей и их настройка:

1) Заюзаем builtin модуль Python subprocess, с его помощью запускаем процесс, через который вызываем запуск скрипта на R.

import subprocess def r_spec(command='Rscript', duration, path, temp, path2script): ''' command - команда запуска скрипта R duration - продолжительность файла в секундах path - путь где лежат файлы для анализа './data/voice/clips/' temp - путь для записи csv файла './data/tmpcsv/' path2script - путь до скрипта на R './R/spectr.R' ''' cmd = [command, path2script] + [name, duration, path, temp] p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

2) Запущенный скрипт на R осуществляет обработку аудио в части снятия аудиохарактеристик файла и их записи в файл «data.csv» с использованием библиотек warbleR и tuneR. Передача параметров в скрипт R осуществляется через аргументы как при вызове файла из командной строки.

library(warbleR) library(tuneR) # передача параметров в скрипт R через аргументы как при вызове файла из командной строки # args[1] - имя файла для анализа - вида common_voice_ru_18849003_0_0.wav # args[2] - продолжительность файла в секундах # args[3] - путь где лежат файлы для анализа /data/voice/clips # args[4] - путь для записи csv файла - os.getcwd() + '/data/tmpcsv/' options(echo = F) args <- commandArgs(trailingOnly = T) dataframe <- data.frame(args[1], 2, 1, as.numeric(args[2])) # обработка файлов функциями specprop и specan b <- specprop(spec(readWave(paste0(args[3], args[1])), f = 16000, plot = F)) names(dataframe) <- c("sound.files", "selec", "start", "end") a <- specan(X = dataframe, bp = c(0,29), wl = 512, wl.freq = NULL, threshold = 15, parallel = 1, fast = TRUE, path = args[3], pb = F, ovlp = 50, ff.method = "seewave", wn = "hanning", fsmooth = 0.1) # формирование датафрейма из результатов и запись датафрейма в csv dataframe_2 <- data.frame(a, b) write.table(dataframe_2, file = paste0(args[4], "data_test.csv"), sep = ",", append = T, row.names = F, col.names = F)

На выходе в папке «./data/tmpcsv/» получаем файл csv, в котором записаны аудиохарактеристики файлов, доступный для обработки в Python.

В итоге, мы выяснили, что из Python можно легко запустить скрипт на R и организовать обмен данными с помощью инструментов командной строки. Конечно, есть более продвинутые способы, в частности, взаимодействие с языком R можно производить с помощью библиотек rpy2 и reticulate. Но это уже совсем другая история…

Аналогично с помощью похожих инструментов можно организовать взаимодействие Python с любым другим языком программирования.

0
2 комментария
Lev Romanov

1. У вас объявление функции некорректное, код не запустится: keyword arguments всегда идут после positional arguments:
def r_spec(duration, path, temp, path2script, command='Rscript'):
2. Для чего склеивать два листа, если вы их тут же создаёте? Сделайте сразу один: cmd = [command, path2script, name, duration, path, temp]
3. subprocess.Popen() — довольно низкоуровневая функция, вам отлично подойдёт subprocess.run()

Ответить
Развернуть ветку

Комментарий удален модератором

Развернуть ветку
NTA
Автор

1. Да, спасибо, действительно опечатка. В рабочем варианте передача данных в функцию выглядит как у Вас. 
2. Два листа были реализованы только для простоты восприятия исходных данных, которые передавались скрипту на R.
3. Такой вариант опробовался. subprocess.run() хоть и запускался без ошибок, но скрипт на R не отрабатывал, то есть csv не создавался. При этом subprocess.Popen() отработал, поэтому остановились на таком варианте.

Ответить
Развернуть ветку
-1 комментариев
Раскрывать всегда