Вызов исполняемого файла Python для ОС из другого процесса Python - PullRequest
0 голосов
/ 16 сентября 2018

Я использую subprocess.Popen для вызова внешнего скрипта Python из моего установленного Приложения, связанного с помощью PyInstaller. Формат этой команды примерно такой:

subprocess.Popen(["/usr/bin/python", "/path/to/exe/SDK.py"],
                 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE, shell=False)

Я успешно проверил это на Windows и MacOS - оба могут запустить внешний скрипт. Однако на других ОС Posix я получаю следующую ошибку:

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
ImportError: No module named site

Теперь я понимаю, что этот вопрос задавался ранее, и обычно он имеет значение PYTHONHOME с неправильным значением. Однако, если я запускаю команду в формате, похожем на:

PYTHONHOME=/usr /usr/bin/python /path/to/exe/SDK.py

Я не получаю ошибок в журналах, но скрипт SDK.py не выполняется.

Поэтому, чтобы доказать, что это не проблема с моим сценарием; Я установил свою собственную версию Python на компьютер - после этого сценарий был успешно выполнен. Я проверил как /usr/bin/python, так и /home/vagrant/Python-2.7.15/python, без необходимости указывать PYTHONHOME в команде подпроцесса.

Однако мне все еще нужно разрешить пользователям выполнять сценарий SDK.py с использованием встроенной версии Python для ОС.

Итак, чтобы сделать это, я попробовал другие вещи:

  1. Использование sys.executable в вызове subprocess.Popen для выполнения SDK.py.

(значение которого было: /opt/program_name/lib/program_name)

  1. Принудительное заполнение PYTHONPATH & PYTHONHOME путем явной настройки среды:

    import os
    env = os.environ.copy()
    env['PYTHONHOME'] = ''
    env['PYTHONPATH'] = ''
    subprocess.Popen(["/usr/bin/python", "/path/to/exe/SDK.py"], env=env)
    

Кто-нибудь может объяснить, как я могу вызвать системную версию Python из внешнего подпроцесса, как этот?

EDIT: Вывод при вызове Python в подробном режиме (из CLI):

>>> from sys import executable
>>> executable
'/usr/bin/python'
>>> import _csv
# trying _csv.so
# trying _csvmodule.so
# trying _csv.py
# trying _csv.pyc
# trying /usr/lib64/python2.7/_csv.so
# trying /usr/lib64/python2.7/_csvmodule.so
# trying /usr/lib64/python2.7/_csv.py
# trying /usr/lib64/python2.7/_csv.pyc
# trying /usr/lib64/python2.7/plat-linux2/_csv.so
# trying /usr/lib64/python2.7/plat-linux2/_csvmodule.so
# trying /usr/lib64/python2.7/plat-linux2/_csv.py
# trying /usr/lib64/python2.7/plat-linux2/_csv.pyc
# trying /usr/lib64/python2.7/lib-dynload/_csv.so
dlopen("/usr/lib64/python2.7/lib-dynload/_csv.so", 2);
import _csv # dynamically loaded from /usr/lib64/python2.7/lib-dynload/_csv.so

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Это не полный ответ, но ради полноты я приведу здесь две вещи, которые сработали - и какой подход мы использовали в конце.

  1. По какой-то странной причине, когда мой коллега сделал это:

env = os.environ.copy() env['LD_LIBRARY_PATH'] = env['PATH']

Это позволило нам вызвать подпроцесс, когда мы передали этот env в вызов Popen() следующим образом:

self.process = subprocess.Popen(sdk_executable_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, env=env)

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

  1. Когда мы создали virtualenv для python, используя пакет pip с тем же именем, и мы назвали SDK, используя этот исполняемый файл python - SDK успешно запустится. Причина этого до сих пор неизвестна, но поскольку это SDK: мы решили, что для возможного SDK Developer целесообразно запускать его в среде, отличной от Python «из коробки» в Linux.
0 голосов
/ 17 сентября 2018

Я попытаюсь провести вас через процесс проверки установки Python на CentOS 7.

Прежде всего, откройте окно терминала и проверьте установку RPM-пакетов python:

$ rpm -V python python-libs

Если вы не получаете вывод, все в порядке. Затем проверьте переменные среды:

$ env | grep PYTHON

Там также не должно быть никакого вывода. Если есть упоминания о PYTHONHOME или PYTHONPATH, сбросьте их. Теперь проверьте, что Python думает о пути по умолчанию:

$ /usr/bin/python
Python 2.7.5 (default, Jul 13 2018, 13:06:57) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from sys import path
>>> print path
['', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages']

Вы также сможете импортировать модуль site без проблем:

>>> import site
>>> print site
<module 'site' from '/usr/lib64/python2.7/site.pyc'>

Если все в порядке, попробуйте запустить скрипт из той же командной строки, в которой вы выполняли тесты.

...