Рубрики
Без рубрики

Интеграция Node.js & Python для написания кросс-языковых модулей с использованием PyExecJS

В этом уроке вы узнаете, как писать кросс-языковые модули с помощью PyExecJS.

Автор оригинала: Kyle J. Roux.

Цель

Чтобы ответить на неизбежный первый вопрос “почему”, я делаю этот учебник, потому что в последнее время я пишу все больше и больше JavaScript , и я использую paver , который является модулем Python, для автоматизации моих задач сборки JavaScript (например, компиляция CoffeeScript и минификация.)

Теперь, в попытке свести к минимуму фактический объем JavaScript, который я пишу, я хотел бы добавить ng-аннотацию в качестве шага в процессе сборки. Это позволит мне написать весь мой угловой код, не думая о его внедрении зависимостей, но все же используя его преимущества. Однако в настоящее время нет модуля Python, который я мог бы использовать для запуска кода через ng-annotate , который является библиотекой JavaScript.

PyExecJS

Как мы будем писать кросс-языковые модули?

С модулем Python PyExecJS ! PyExecJS позволяет нам писать функции на JavaScript, которые мы затем можем вызывать из нашего кода Python. Функции JavaScript, которые мы пишем, могут возвращать данные прямо в наш код Python. PyExecJS также позволяет нам выбрать движок JavaScript для использования, что помогает , поскольку нам нужно будет использовать движок узлов для работы с ng-annotate , поскольку ng-annotate является модулем узла.

Итак, для начала давайте использовать pip для установки библиотеки pyexecjs:

$ pip install pyexecjs

Далее мы запустим наш файл модуля (который мы будем называть ng_annotate.py ) путем импорта функции get из execjs, которая позволяет нам запрашивать определенный движок JavaScript для запуска нашего кода.

from execjs import get
import os

runtime = get('Node')

Теперь, когда у нас есть механизм выполнения для работы, у нас есть то, что нам нужно.

Далее, нам нужно будет убедиться, что если кто-то установит это, у него будет доступ к модулю узла ng-annotate . Итак, создайте файл с именем package.json и поместите в него это:

{
    "dependencies":{
        "ng-annotate":"*"
    }
}

Наконец, нам просто нужно добавить инструкцию для запуска npm install перед ее использованием.

А теперь вернемся в наш файл модуля, нам нужно написать нашу функцию JavaScript, которую будет использовать наш модуль, а также убедиться, что он может получить доступ к папке node_modules , которая будет добавлена npm install . Мы делаем это, оборачивая ваш JavaScript в вызов runtime.compile , чтобы мы могли получить доступ к функциям внутри нашего кода Python.

context = runtime.compile('''
    module.paths.push('%s');
    ng = require('ng-annotate');
    function annotate(src,cfg){
          return ng(src,cfg);  
    }
''' % os.path.join(os.path.dirname(__file__),'node_modules'))

Теперь мы можем вызвать функцию annotate из нашего кода Python с помощью context.call('annotate',*args) , и она вернет результат точно так же, как в JavaScript. Поэтому, чтобы превратить это в стандартную функцию Python, которую мы можем использовать, это так же просто, как:

def ng_annotate(src,cfg=None):
    if cfg is None:
        cfg = dict(add=True)    
    return context.call('annotate',src,cfg)

Теперь мы можем использовать его из нашего кода Python с помощью from ng_annotate import ng_annotate и вызова этой функции, но давайте также сделаем его удобным инструментом командной строки:

import sys

def main():
    print ng_annotate(open(sys.argv[-1],'r').read()) 

if __name__ == "__main__":
    main()

Вот и все ng_annotate.py файл для справки:

import os
import sys
from execjs import get

runtime = get('Node')
context = runtime.compile('''
    module.paths.push('%s');
    var ng = require('ng-annotate');
    function annotate(src,cfg){
        return ng(src,cfg);
    }
''' % os.path.join(os.path.dirname(__file__),'node_modules'))

def ng_annotate(src,cfg=None):
    if cfg is None:
        cfg = dict(add=True)
    return context.call('annotate',src,cfg)

def main():
    print ng_annotate(open(sys.argv[-1],'r').read())

if __name__ == "__main__":
    main()