2014-09-18 1 views
2

Я пытаюсь автоматизировать создание исполняемого файла для моей программы на 32 и 64 бит с помощью cx_Freeze. У меня есть две отдельные установки python 3.4 (32 и 64 бит) со всеми необходимыми пакетами, которые соответствуют их соответствующим архитектурам.Импорт неправильных пакетов при вызове скрипта python из другого скрипта python через подпроцесс

Однако, когда я выполняю скрипт, который вызывает различные установки python через подпроцесс, подпроцессы вызываемые подпроцессы python импортируют неправильные пакеты. Они и импортируют пакеты, из которых был выдан исходный сценарий, и не пакеты установки python, которые вызывались в подпроцессе.

Minimal пример вызывается с 64-битным питоном:

#! coding=utf-8 
import subprocess as sp 
sp.call(["python34-32","test.py"]) 
sp.call(["python34","test.py"]) 

test.py содержит только строку:

Второго процесс, который также вызывает 64биный питон не будет иметь проблема. Но 32bit выбросит следующее сообщение об ошибке:

ImportError: DLL load failed: %1 is not a valid Win32 application. 

Это происходит потому, что подпроцесс, который звонит 32bit питона, импорт cx_freeze из 64-битных питона. Ситуация также может быть отменена. Когда основной скрипт выполняется с 32-битным питоном, возникает одна и та же ошибка, однако теперь это связано с тем, что 64-битный питон, вызываемый в суперпроцессе, импортирует 32-битный пакет замораживания.

Как я могу остановить это поведение и сказать ему импортировать из соответствующего источника?

Я использую Windows 7 x64 и PyDev как IDE, в случае, если это релевантно, что это, вероятно, так.

EDIT: По-видимому, это работает, когда главный скрипт выполняется из командной строки внутри исходного каталога. Благодаря комментариям ниже, я думаю, проблема связана с тем, как PyDev устанавливает переменные среды.

+2

Может быть, это экологическая проблема? подпроцессы наследуют текущую среду, поэтому, возможно, новый интерпретатор смотрит на неправильный 'PYTHONPATH'. – Bakuriu

+1

Кстати, знаете ли вы [соображения безопасности] (https://docs.python.org/3.4/library/subprocess.html#security-considerations) использования 'shell = True'? Если вы не используете какую-либо специфичную для оболочки функцию, вы должны * не * указывать 'shell = True' и просто делать:' sp.call (['python34-32', 'test.py']) '. Если вам не нравится писать команду в виде списка, вы можете использовать 'shlex.split':' import shlex; sp.call (shlex.split ('python34-32 test.py')) '. – Bakuriu

+3

Что произойдет, если вы запустите 'python34-32 test.py' из командной строки в том же каталоге? – jfs

ответ

3

По-видимому, PyDev устанавливает переменную окружения PYTHONPATH, и это путь, который использует подпроцессы для загрузки своих пакетов.

Если я выполнить следующий сценарий в 64-битной Python:

#! coding=utf-8 
import subprocess as sp 

sp.call(["python34-32", "test.py"]) 

тогда test.py содержит строки:

import os 
print(os.getenv("PYTHONPATH")) 

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

Я предполагаю, что я должен изменить переменную PYTHONPATH перед вызовом 32-битного питона. Кто-нибудь знает как это сделать?

EDIT: изменение переменной PYTHONPATH в среде подпроцесса сделало трюк. Выполнение следующих действий в 64-битный питон будет работать

#! coding=utf-8 
import subprocess as sp 
import os 

env = os.environ 
env["PYTHONATH"] = "{INSERT FOLDERS TO 32bit PYTHON}" 
sp.call(["python34-32", "test.py"], env=env) 

Благодаря bakuriu для получения меня на верном пути.

+0

Внутри скрипта Python проверьте 'sys.path'. 'PYTHONPATH' является лишь частью этого. 'call ([" python34-32 "," test.py "])' должен работать, даже если вы удалите 'PYTHONPATH' envvar:' del env ["PYTHONPATH"} 'перед передачей дочернему процессу. – jfs