Вызов модуля Python 2.7 в Python 3.2

У меня есть программа с графическим интерфейсом, которую я разработал на Python 3.2 для извлечения различных продуктов геопространственных данных. Мне нужно вызвать модуль, который я разработал в Python 2.7.

Я ищу способ вызвать код Python 2.7 с помощью интерпретатора Python 2.7 внутри программы Python 3.2. Я не могу портировать 2.7 на Python 3.2, так как он использует версию Python, установленную с ESRI ArcMap, и полагается на модуль arcpy, который недоступен для Python 3. Моей единственной идеей сейчас было бы использовать подпроцесс для вызова модуля как пакетного процесса. однако это немного беспорядочно, и я бы предпочел, чтобы эти две программы имели какое-то отношение.

Заранее спасибо.


person lamb    schedule 19.05.2016    source источник


Ответы (3)


Попробуйте использовать subprocess.check_output(['C:\\python27\\python.exe', 'yourModule.py'])

Если вы хотите вызвать определенную функцию в файле 27, вы можете использовать больше системных аргументов. Вызов будет выглядеть так:

subprocess.check_output(['C:\\python27\\python.exe', 'yourModule.py', 'funcName'])

А в файле 27 можно добавить:

import sys
if __name__=='__main__':
    if 'funcName' in sys.argv:
        funcName()
     else:
        #... execute normally
person kmaork    schedule 19.05.2016
comment
Знаете ли вы, как я мог бы вызвать определенную функцию этого файла Python с аргументами? - person lamb; 19.05.2016
comment
Хотя изначально я никогда не собирался использовать подпроцесс, он выполняет свою работу, как и ожидалось, спасибо :) - person lamb; 24.05.2016

Вы можете создать процесс python 2.7 как сервер, обрабатывающий запросы RPC из вашего графического интерфейса, работающего на 3.2. Это будет работать либо по сети, либо по локальным каналам, либо по общей памяти, либо по шине сообщений вашей системы, или многими другими способами. Вам просто нужно перевести API вашей библиотеки в какие-то сериализованные сообщения.

Допустим, в вашей библиотеке есть функция: (суперупрощенный пример)

def add(a, b):
    return a+b

Вы бы поместили это на какой-нибудь сервер, скажем, в фласк-приложение, которое делает:

@app.route("/add", methods=["POST"])
def handle_add():
    data = request.get_json()
    ret = your_lib.add(data['a'], data['b'])
    return jsonify(ret)

а на стороне клиента отправьте и распакуйте значения, используя что-то вроде запросов.

Вы даже можете сделать его довольно прозрачным, реализовав модуль транслятора с методами, названными так же, как и сама библиотека, и выполнив import your_http_wrapper as your_library_name.

Хитрость теперь заключается в том, чтобы убедиться, что все ваши параметры могут быть сериализованы и что вы можете реально отправлять все аргументы/возвращаемые значения в разумное время при каждом вызове. Кроме того, вы теряете возможность изменять содержимое переменных, которые вы передаете в оболочку, потому что сервер будет изменять только локальную копию (если вы также не реализуете сериализацию всех этих модификаций).

person viraptor    schedule 19.05.2016

Несколько поздно, но на случай, если кто-то наткнется на эту тему:

Я написал модуль, который прозрачно запускает части программы в других интерпретаторах Python. По сути, он предоставляет декораторы и базовые классы, которые заменяют функции и объекты прокси-серверами, взаимодействующими с другими интерпретаторами.

Он предназначен для совместимости, например. выполнение python2 только кода в python3 или доступ к модулям C из pypy.

В следующем примере цикл выполняется в 4 раза быстрее с использованием pypy, чем с обычным python.

#!/usr/local/bin/python
from cpy2py import TwinMaster, twinfunction
import sys
import time
import math


# loops in PyPy
@twinfunction('pypy')
def prime_sieve(max_val):
    start_time = time.time()
    primes = [1] * 2 + [0] * (max_val - 1)
    for value, factors in enumerate(primes):
        if factors == 0:
            for multiple in xrange(value*value, max_val + 1, value):
                primes[multiple] += 1
    return {'xy': [
        [primes[idx] == 0 for idx in range(minidx, minidx + int(math.sqrt(max_val)))]
        for minidx in range(0, max_val, int(math.sqrt(max_val)))
        ], 'info': '%s in %.1fs' % (sys.executable, time.time() - start_time)}


# matplotlib in CPython
@twinfunction('python')
def draw(xy, info='<None>'):
    from matplotlib import pyplot
    pyplot.copper()
    pyplot.matshow(xy)
    pyplot.xlabel(info, color="red")
    pyplot.show()

if __name__ == '__main__':
    twins = [TwinMaster('python'), TwinMaster('pypy')]
    for twin in twins:
        twin.start()
    data = prime_sieve(int(1E6))
    draw(**data)
person MisterMiyagi    schedule 16.11.2016
comment
еще не использовать это, однако это выглядит очень полезным, спасибо! - person lamb; 17.11.2016