我想从外部进程导入内部的exe模块。我可以在IDE中很好地完成这个任务,但是当我用pyinstaller打包项目时,运行它,就找不到模块了。
高层流如下所示:

从外部maya_app导入userSetup.py返回一个错误:ImportError: No modules named maya_app
This post似乎对我有帮助,但是我的设置有一些东西阻碍了这个解决方案的工作。否则我就是做错了。
是否有可能将模块从一个exe导入另一个exe?谢谢!
代码:
launch_maya.py
import os
import sys
import subprocess
from PySide2 import QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
# GUI
btn_launch = QtWidgets.QPushButton('launch maya')
btn_launch.clicked.connect(self.on_launch)
# Layout
main_layout = QtWidgets.QHBoxLayout(self)
main_layout.addWidget(btn_launch)
self.setLayout(main_layout)
# Root path exe vs ide
if getattr(sys, 'frozen', False):
self.root_path = sys._MEIPASS
else:
self.root_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
def _set_app_envs(self):
_envs = os.environ.copy()
_envs['MAYA_SCRIPT_PATH'] = os.path.join(self.root_path, 'scripts').replace('\\', '/')
# Python path envs
_python_path_list = [
'C:\\Program Files\\Autodesk\\Maya2020\\Python\\Lib\\site-packages',
'C:\\Program Files\\Autodesk\\Maya2020\\Python\\DLLs',
os.path.join(self.root_path, 'scripts').replace('\\', '/'),
os.path.join(self.root_path, 'internal_source', 'maya_app')
]
# PYTHONPATH exe vs ide
if getattr(sys, 'frozen', False):
_envs['PYTHONPATH'] = os.pathsep.join(_python_path_list)
_envs['PYTHONHOME'] = 'C:\\Program Files\\Autodesk\\Maya2020\\bin'
else:
_envs['PYTHONPATH'] += os.pathsep + os.pathsep.join(_python_path_list)
return _envs
def on_launch(self):
# Maya file path
file_path_abs = '{}/scenes/test.mb'.format(self.root_path).replace('\\', '/')
print(file_path_abs)
app_exe = r'C:/Program Files/Autodesk/Maya2020/bin/maya.exe'
_envs = self._set_app_envs()
if os.path.exists(file_path_abs):
proc = subprocess.Popen(
[app_exe, file_path_abs],
env=_envs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Widget()
window.resize(400, 400)
window.show()
sys.exit(app.exec_())bundle.spec
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
added_files = [
('./scenes', 'scenes'),
('./scripts', 'scripts')
]
a = Analysis(['launch_maya.py'],
pathex=[
'D:/GitStuff/mb-armada/example_files/exe_bundle',
'D:/GitStuff/mb-armada/dependencies/Qt.py',
'D:/GitStuff/mb-armada/venv/Lib/site-packages',
],
binaries=[],
datas=added_files,
hiddenimports=['internal_source', 'internal_source.maya_app'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='bundle',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='bundle')maya_app.py
import os
import sys
import subprocess
from PySide2 import QtWidgets
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
# GUI
btn_launch = QtWidgets.QPushButton('say hey')
btn_launch.clicked.connect(self.on_say_hey)
# Layout
main_layout = QtWidgets.QHBoxLayout(self)
main_layout.addWidget(btn_launch)
self.setLayout(main_layout)
print('I should be alive')
def on_say_hey(self):
print('hey')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWidget()
window.resize(100, 100)
window.show()
sys.exit(app.exec_())userSetup.py
import os
import sys
import maya.cmds as mc
print('hey')
def tweak_launch(*args):
print('Startup sequence running...')
os.environ['mickey'] = '--------ebae--------'
print(os.environ['mickey'])
root_path = os.getenv('_MMM_ROOT_PATH')
main_app_path = os.path.join(root_path, 'internal_source')
if not root_path in sys.path:
sys.path.append(main_app_path)
from internal_source import maya_app
w = maya_app.MainWidget()
w.show()
print('window should be up')
mc.evalDeferred("tweak_launch()")发布于 2020-05-12 01:18:45
在最高级别,这似乎是关于你发射的玛雅的路径管理--大概发射应用程序知道它有自己的路径,你想发射的玛雅人需要被告知它们的存在。
要做到这一点,最可靠、最不神奇的方法就是让您的启动程序将它需要与maya共享的脚本解压缩到一个已知的位置--一个隐藏的目录,甚至一个特定于会话的临时目录,这将使您在启动程序运行时获得最新版本的可能性最大。
在启动maya时,您可以通过几种方式传递路径--可能最简单的方法就是使用site.addsitedir将它们放置在会话的路径上,而不是依赖于玛雅的许多其他可能的搜索位置。您可以使用-c mel标志启动maya,并在启动时传递一个python命令,这样您就可以完全从启动程序控制此行为,而不必担心与userSetup.py的交互。这样的东西可以让玛雅得到你的东西:
# unpack the 'payload' of scripts to share to a
# known location with something like pkgutil.get_data()
# https://docs.python.org/3/library/pkgutil.html
# note the single quotes -- you need them to handle escaping!
py_cmd = "import site; site.addsitedir('{}'); import my_startup_module"
python_to_execute = py_cmd.format(path_to_unpacked_modules)
# again, note annoying escapes
start_cmd = '\"python(\"{}\");\"'.format(python_to_execute)
maya_session = subprocess.Popen(['maya.exe', '-c', start_cmd])如果您的exe已将文件解压缩到path_to_unpacked_modules,则maya将运行mel命令,该命令将调用python,将模块dir添加为站点包目录,然后导入并运行my_startup_module (从该位置)。这样您的启动程序就可以控制启动过程,并且不必单独使用userSetup.py --此外,由于它不涉及env,所以您不必费力地同时运行不同的会话。
如果您想要共享的代码只是一堆模块(没有二进制扩展名),您可以将模块保存在一个zip文件中,并将其添加到path - python中,这样就可以自动在zip文件中找到模块。这既节省了解压缩时间,也确保您没有从旧运行中遗留下来的PYC文件。
在这些线程中有很多有用的信息:https://tech-artists.org/t/python-maya-startup-script/2145/17 https://tech-artists.org/t/deploy-tools-for-your-maya-team/5029/13
https://stackoverflow.com/questions/61671637
复制相似问题