본문 바로가기
SW 개발/Python

Python 소스 숨기는 방법: pyc 활용 (Bytecode로 컴파일)

by Kibua20 2020. 6. 30.

Python은 기본적으로 인터프리터 언어이기 때문에 별도의 컴파일과 링크 없이 실행(=해석) 가능합니다.   상용 프로그램으로 배포하는 경우나 보안 상 파이썬 소스 코드의 일부분을 숨겨야 하는 경우 Byte code로 변환하여 pyc (pyo) 파일을 사용할 수 있습니다.   

 

pyc 파일은 C 언어처럼 기계어로 컴파일한 것이 아니라 Byte code로 '변환'한 것이기 때문에 조금만 노력하면 원래의 소스 코드로 de-compile이 가능하기 때문에 절대적으로 소스 코드의 보안이 유지된다고 믿어서는 안 됩니다. 다만 소스코드를 보기 힘들게 하는 정도로 이해해야 합니다. 

 

Python 공식 문서에는 pyc로 컴파일하는 py_compile()는 아래와 같이 설명되어 있습니다.  https://docs.python.org/ko/3.8/library/py_compile.html

파이썬 공식 문서:  https://docs.python.org/ko/3.8/library/py_compile.html


주의 사항

Byte code로 컴파일된 pyc 파일은 플랫폼 독립적이지만, 동일한 Python 버전에서만 동작합니다.  PC에서 설치한 Python 버전과 Compiled Python 파일(*. pyc 파일)을 생성한 Python 버전이 일치하지 않는 경우 동작하지 않으며, 하위 버전의 호환성도 없습다.  Python 버전별로 magic 넘버가 다르면 pyc 파일에서 magic number를 확인하는 방법은 여기를 확인해주세요. 


Command line에서 pyc 파일로 컴파일하는 방법

# test.py 파일을 컴파일, pyc 파일은 __pycache__ 폴더에 저장

$ python3 test_compiled.pyc

 

# 확장자가 *.py 파일을 모두 컴파일

$ python3 -m py_compile *.py

# 폴더 하위에 모든 py 파일 찾아서 __pycache__ 폴더에 bytecode 파일(pyc)을 생성한다. 

$ python3 -m compileall ./   (--> 폴더 지정해야 함)

 

Python code 상에서 pyc 파일로 컴파일하는 방법

프로젝트에서 setup.py 와 같은 python 파일을 컴파일하는 스크립트를 작성할 때 유용합니다. 

 

#py_comile 모듈을 import 한다. 

import py_compile

 

# sample.py 파일을 컴파일한다.
py_compile.compile(sample.py)

 

pyc 파일 호출하는 방법 

python을 호출할 때 pyc 파일은 전달하면 pyc 파일을 실행합니다.  pyc 파일만 있어도 모듈 간의 import 가 가능합니다.

 

# pyc 파일 실행

$ python3 sample.pyc

 

Python code 최적화 (pyo) 파일 생성 (의미 없음)

Pyo 파일 사용은 추천하지 않습니다. 파이썬 인터프리터를 -O 옵션과 함께 사용하면 최적화된(optimized) 코드가 pyo 파일로 생성됩니다. (assert 구문만이 제거되는 수준)  pyc 파일이나 pyo 파일이 존재한다고 해서 프로그램 실행이 빨라지는 것은 아니고, 모듈들은 프로그램이 load 될 때 읽어오기 때문에, 프로그램 load 시간만 빨라질 뿐입니다. 



예제

아래 sample code는 Project 폴더에서 test.py, hello.py, testbin (binary 실행파일)이 있는 경우 확장자가 py 파일을 target 폴더로 pyc 파일로 컴파일하는 코드입니다.  py 이외에 파일은 shutil.copy()로 파일 변경 없이 그대로 copy 합니다. 

import os
import shutil
import py_compile

def main():
    # py 파일이 있는 폴더
    src_dir = os.getcwd()
    # pyc 파일을 copy할 폴더 이름
    target_dir = os.path.join(src_dir, 'compiled')

    src_list = ['test.py', 
                'hello.py', 
                'testbin']

    # target_dir폴더가 없으면 생성
    if not os.path.exists(target_dir):
        print ('Target Dir is NOT exist', target_dir)
        os.mkdir (target_dir)

    # 소스파일의 리스트에서 파일 하나씩 처리한다
    for dst_file in src_list:
    	# py 파일을 하나씩 pyc 로 bytecode로 컴파일한다.
        if (dst_file.endswith('.py')):
            # py--> pyc 로 확장자 변경
            compiled_py = dst_file.replace('.py', '.pyc')
            print (dst_file, '-->', fc)
            # py 파일을 pyc 로 컴파일하고 output을 target dir에 저장
            py_compile.compile(f, os.path.join(target_dir, dst_file))          
        else:
            # *.py 파일이 아닌 경우 copy
            shutil.copy(os.path.join(src_dir,dst_file), target_dir)
 

 

관련 글

[모바일 SW 개발/Python] - Python 폴더 및 파일 처리 함수 모음

[개발환경] - 우분투 작업 스케줄러 Crontab 사용법, 디버깅, 주의 사항

[모바일 SW 개발/Python] - Python: 폴더 백업 기능 구현 (7zip 압축, Sample code)

[모바일 SW 개발/REST API] - JWT(JSON Web Token) Encoding 방법 (Python sample code)

[모바일 SW 개발/Android] - [실패 사례] WSL(Windows Subsystem for Linux) 에서 Android 빌드하기

[모바일 SW 개발/Python] - Python 에러: /usr/bin/env: `python3\r': 그런 파일이나 디렉터리가 없습니다

[모바일 SW 개발/Python] - Python 표준 입출력(stdin/stdout) 활용 - 리눅스 프로그램과 연동

[모바일 SW 개발/Python] - Python smtplib 사용한 email 발송 예제 (gmail)

[모바일 SW 개발/Python] - Python SyntaxError: Non-ASCII character in file on, but no encoding declared

[모바일 SW 개발/Python] - Python JSON 사용 시 TypeError: Object of type bytes is not JSON serializable

[모바일 SW 개발/Python] - Python 2.7과 3.8호환성: a bytes-like object is required, not 'str'에러 수정

[모바일 SW 개발/Python] - [Tips] Python: XML Parsing 시 multiple elements on top level

[모바일 SW 개발/Android] - Android 11 기능 소개




댓글