이러한 .pyc 파일을 Compiled Bytecode 라 부르며, 소스코드를 숨길 수 있을 뿐만 아니라 파이썬 모듈을 Import 할 때 속도 향상 또한 가져다주는 장점을 가지고 있습니다.
Maya Python 파일은 Python API 뿐만 아니라 Python Script 파일, 심지어 MEL 파일도 Python 으로 wrapping 해서 .pyc 파일로 배포가 가능합니다. 따라서 소스코드 뿐만 아니라 UI 등 어떤 형태의 스크립트 파일도 배포할 수 있습니다.
이번 포스팅에서는 먼저 Python Maya Script 파일을 .pyc 파일로 제작하고, import 하는 과정을 설명하도록 하겠습니다.
1. Python Script 파일을 .pyc 파일로 제작하기
아래 파일은 Mesh 를 선택하고 버튼을 누르면 해당 Mesh 의 이름을 반환하는 간단한 기능을 가지고 있는 UI 를 Maya Python Script 로 구현한 파일입니다.
※주의!
(위 파일을 보통 배포되는 형태처럼, Maya Script Editor 에서 전체 복사이후 실행 (Ctrl+A -> Ctrl+C -> Ctrl+V -> Ctrl+Enter) 시키면, UI 는 뜨지만 버튼들이 제대로 동작하지 않을 것입니다. 이것은 내부 모듈 실행 이름이 다르기 때문인데, 관련한 내용은 잠시 뒤에 설명할 것입니다.)
위 파일을 테스트해보고 싶으면, Maya 에서 Python 모듈을 Import 하는 형태로 사용해야 합니다. Python 모듈을 Import 하고 싶으면 해당 Python 파일을 기존 Python Path 에 넣거나, 해당 파일이 있는 Path 를 Python Path 에 추가해주면 됩니다. 해당 소스코드는 아래를 참조하세요.
#Python Path 확인하기
import sys
for i in sys.path :
print i
#Python Path 추가하기
import sys
srcPath = "C:\.... (Custom Path)"
if srcPath not in sys.path :
sys.path.append(srcPath)
위와 같이 Module 을 Import 할 Path 를 잡아주고 나면, 해당 Python Script 를 Import 할 수 있습니다. 다음 명령어로 Import 해서 UI 를 실행시켜 봅시다.
#Python Module Import
import testUI
그러면, 아래 그림과 같은 UI 가 뜨는 것을 확인할 수 있습니다. 각 버튼을 눌러서 제대로 작동하는지 확인해 봅니다.
간단한 UI...지만 최대한 Maya 표준에 맞게 제작한 UI
버튼이 제대로 동작하는 지 확인하고 나면, 해당 Python Script (testUI.py) 를 넣어 두었던 폴더에 가 봅니다. 그러면 Python Script 의 Compiled Bytecode Version 인 .pyc 파일이 생성되어 있는 것을 확인할 수 있습니다.
.pyc 가 갑툭튀
이렇게 해당 Python 파일을 Module 로 Import 하면 .pyc 파일이 자동으로 생성됩니다. 이것이 .pyc 파일을 만드는 가장 간단한 방법입니다.
Python 파일을 .pyc 파일로 만드는 또 다른 방법은 직접 컴파일 하는 방법이 있습니다. 다음 소스코드로 직접 컴파일해 봅시다.
※ 주의!
직접 컴파일할 때, 경로명은 슬래시 (/) 혹은 백슬래시 2개 (\\) 를 사용해야 합니다. 백슬래시 1개 (\) 는 작동하지 않습니다.
역시 .pyc 파일이 생성되어 있는 것을 확인할 수 있습니다.
2. .pyc 파일을 import 하기
.pyc 파일을 import 하는 방법은 매우 간단합니다. .py 파일을 import 하는 것과 똑같이 그냥 .pyc 파일을 import 하면 됩니다.
.pyc 파일이 잘 import 되는가를 확인하기 위해, 메모리를 청소하기 위해서 Maya 를 한번 껐다 켜고, .pyc 파일만 다른 폴더에 복사해둡니다.
그런 다음 다시 Maya 를 켜서, 먼저 다음 명령어로 testUI 를 Import 할 수 없음을 확인합니다. 당연히 아래 그림과 같은 Import Error 메시지가 떠야 합니다. (만약 testUI.py 파일을 기존 Python Path 에 넣어두었다면 import 가 되어버릴 것입니다. 이러면 .pyc 파일만 확인할 수가 없으므로 testUI.py 파일을 지워주어야겠죠?)
import testUI
우리를 겁나게 하는 시뻘건 에러 하지만 이번엔 이게 정상
그리고 testUI.pyc 파일이 담겨 있는 path 를 다음과 같이 등록해준 다음, import 해 봅시다.
srcPath = "C:\...(Custom Path)"
import sys
if srcPath not in sys.path:
sys.path.append( srcPath )
import testUI
아까와 같이 UI 가 제대로 작동하면 .pyc 파일을 제대로 Import 한 것입니다.
.pyc 파일을 열어 보아도, 소스코드 내용을 확인할 수가 없습니다.
확인할수가 업ㅂ어
.pyc 파일의 import 를 정리하면 다음과 같습니다.
Module 로 Import 됩니다.
- 기존 Python Module 을 사용하는 것처럼, 모듈명.함수() 형태로 모듈 안의 함수들을 사용할 수 있습니다.
- 위에 제시된 예제 파일처럼 모듈 안에 들어있는 것이 Class 라면, Class 의 객체를 만들어 사용하거나, 직접 Class 의 멤버함수를 사용할 수 있습니다.
- ex) import testUI
myUI = testUI.TestUI()
myUI.showMyWindow()
또는
import testUI
testUI.testUI().showMyWindow()
Import 되는 순간 실행됩니다.
- Import 되는 순간 .pyc 의 내용들이 메모리에 올라가게 됩니다.
- 예제 파일에서는 import maya.cmds as mc 와 TestUI().showMyWindow() 가 전역적으로 실행되고, 클래스가 메모리에 올라갑니다.
Maya UI 파일을 .pyc 파일로 배포할 때 주의사항
UI 파일을 .pyc 파일로 배포할 때에 주의사항이 있습니다. 각종 UI 에는 다양한 형태의 '버튼' (이라고 통칭합시다) 이 있는데, 이런 버튼은 마야에서 command 를 실행하게 됩니다. 예를 들면
mc.button(label="Select mesh and press", align="center", command="testUI.TestUI().importMesh()")
예제에 있는 버튼의 한 예입니다. "Select mesh and press" 라는 버튼을 누르면 "testUI.TestUI().importMesh()" 라는 커맨드를 실행하게 되는 버튼입니다.
이와 같이, UI 의 각종 버튼들은 command 인자로 받는 " " 쌍따옴표 안에 들어있는 커맨드를 그대로 실행합니다. 때문에, module 명을 임의로 import 하였을 경우 command 를 실행시키지 못합니다.
예를 들어, 다음과 같이 myUI 라는 임의의 이름으로 module 을 import 한다면
import testUI as myUI
다른 Python module 들은 myUI.함수명() 과 같은 형태로 실행시킬 수 있지만, Maya UI 의 경우 command 를 임의의 모듈명을 받아서 실행시킬 방법이 없습니다.
따라서 UI 파일이 함수의 나열 형태로 구성되어 있다면 UI 내의 command 부분을
command = "모듈명.함수명()"
으로 정해주어야 하거나, 예제와 같이 클래스 형태로 구성되어 있다면
command = "모듈명.클래스명().함수명()"
으로 정해 주어야 하고, 모듈을 import 할 때에는
import 모듈명
으로만 import 해야 UI 를 .pyc 파일로 배포하고, 정상적으로 사용할 수 있습니다.
3. Mel 파일을 .pyc 파일로 제작하기
Mel 파일을 .pyc 파일로 제작하는 방법은 간단합니다. Mel Script 를 Python Script 에서 실행시킬 수 있도록 바꾸어 주면, 이후 과정은 당연히 Python Script 를 .pyc 로 만드는 과정과 동일합니다. 예제를 보는 것이 이해가 빠를 것입니다.
import maya.mel as mel
mel.eval('polySphere -r 3;')
mel.eval('polyCube -w 2 -h 6;')
mel.eval('polyCylinder -h 7 -sx 10;')
위와 같은 python 파일을 만들어서 컴파일하면 MEL 파일도 .pyc 형태로 배포할 수 있습니다.
4. Maya Python Plug-in 파일을 .pyc 파일로 제작하기
아래 소스코드는 'Hello, World' 를 찍는 간단한 Maya Python Plug-in 파일입니다.
sys.stderr.write( "Failed to register command: %s\n" % kPluginCmdName )
raise
# Uninitialize the script plug-in
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterCommand( kPluginCmdName )
except:
sys.stderr.write( "Failed to unregister command: %s\n" % kPluginCmdName )
raise
이 소스코드를 파이썬 파일로 저장한 다음, Plug-in Manager 에서 불러들여봅니다. 스크립트 에디터에서 spHelloWorld 라는 커맨드를 입력하면 'Hello World!' 라는 텍스트를 출력합니다.
마야 '커맨드' 로 등록했으므로,
MEL 모드에서는 spHelloWorld 를 입력하면 되고,
Python 모드에서는
Import maya.cmds as mc
mc.spHelloWorld()
로 입력해야 합니다.
그렇다면 이 Python 파일을 바로 컴파일 해서, .pyc 형태로 만들면 바로 배포 가능하겠네? 라고 생각할 수 있지만 현실은 그렇지 않습니다. 세상일이 그렇게 마음대로 되던가요. 플러그인 파일 전체를 컴파일 해서 .pyc 파일로 만들면, Maya Plug-in Manager 에서 .pyc 파일이 보이긴 합니다(!). 그러나 제대로 플러그인을 읽어 들이지 못하는 것을 볼 수 있습니다.
비록 눈에는 보이지만
세상 일이 맘처럼 쉽지만은 않은 예.pyc
Python Plug-in 파일을 배포하기 위해서는 코어 부분과 이니셜라이징 부분을 분리해서, 코어 부분은 .pyc 파일로 만들고, Plug-in 이니셜라이징 부분은 해당 .pyc 파일을 Import 하는 .py 파일을 만들어 두 파일을 다 배포하면 됩니다.
먼저 위 코드에서 코어 부분을 다음과 같이 떼어 컴파일합니다.
helloWorldCore.py
import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
kPluginCmdName = "spHelloWorld"
# command
class scriptedCommand(OpenMayaMPx.MPxCommand):
def __init__(self):
OpenMayaMPx.MPxCommand.__init__(self)
def doIt(self,argList):
print "Hello World!"
# Creator
def cmdCreator():
return OpenMayaMPx.asMPxPtr( scriptedCommand() )
그렇다면 helloWorldCore.pyc 파일이 제작되겠죠? 그리고 나서 이 .pyc 파일을 import 해서 이니셜라이징 하는 파일을 제작합니다. 원본 파일과 달라진 부분을 진한 글씨로 표시하겠습니다.
helloWorld.py
import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx import helloWorldCore as hwc
sys.stderr.write( "Failed to register command: %s\n" % hwc.kPluginCmdName )
raise
# Uninitialize the script plug-in
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterCommand( hwc.kPluginCmdName )
except:
sys.stderr.write( "Failed to unregister command: %s\n" % kPluginCmdName )
raise
그리고 이 helloWorld.py 를 Plug-in Manager 에서 불러들이면 정상적으로 플러그인이 동작하는 것을 확인할 수 있습니다.
정리하면
코어 부분은 .pyc 파일로, 이니셜라이징 하는 부분은 .py 파일로 제작합니다.
이니셜라이징 하는 .py 파일이 코어 파일인 .pyc 파일을 import 해서 사용하므로, .pyc 파일의 위치는 기존 Python Path 에 넣어주거나, 해당 위치를 Python Path 에 추가해주어야 합니다.
이니셜라이징 하는 .py 파일 안에, .pyc 파일이 있는 커스텀 경로를 Python Path 로 등록하는 부분을 추가해 주는 것이 하나의 적합한 배포 형태가 될 것 같습니다.
5. 마치며
1) Python Version
.pyc 파일은 Python version specific 한 파일입니다. 다시 말해서, 다양한 version 의 python 에서 모두 동작하게 만들고 싶으면, 각각의 python 에 맞는 .pyc 파일을 제작해서 배포하여야 합니다.
우리는 Maya Python Script 파일을 배포하므로, Maya 가 사용하는 Python version 이 중요한데, 현재 Maya 2012 의 경우 Python 2.6 을 사용하고 있습니다. (이것이 우리가 Python 2.6 을 설치해야 하는 이유) 그러므로, Python 2.6 버전에서 제작 / 컴파일 하면 되겠습니다.
2) 정말 안전한가?
실컷 설명해 두었지만 안타깝게도 이것이 Python script 를 완벽하게 보호해주는 솔루션이 되지는 못합니다. 구글에서는 손쉽게 Python Script 를 Crack 해서 원본 소스코드를 볼 수 있는 툴을 구할 수 있습니다.
그렇지만 .pyc 가 완전히 보안에 취약하지는 않습니다. 그렇다면 Maya 도 .pyc 형태로 라이브러리를 배포하지 않았겠죠; .pyc 가 일정 용량이 넘어가면 Crack 으로도 소스코드를 풀 수가 없다고 합니다. 즉 소스 코드의 분량이 어느 정도 이상이 되면 보안성이 향상된다는 이야기인데, 여기에 대해서는 사실 좀더 조사가 필요합니다; 따라서 신중한 접근이 필요할 것 같습니다.
재밌는 기능을 발견했다. Maya Python Script 에만 있는 기능은 아니고, Python 자체에 있는 기능인데 3중 따옴표를 쓰면 여러 줄의 문자열을 한 string 에 입력할 수 있다.
mc.expression(s = """pCylinder1.scaleX = 3; \n
pCylinder1.scaleY = 2""")
여러 줄의 expression 을 입력하고 싶을 때 스크립트로 다른 expression 을 입력해서 기존의 expression 을 수정하는 방법은 없는 것 같다. 그러면 또 다른 expression 이 생겨버린다. expression 을 수정하기 위해서는 expression editor 를 이용하는 방법 뿐인듯.