-
Python/PyInstaller/1. What PyInstaller Does and How It Does It코딩/Python 2024. 7. 8. 12:16728x90
원본은 아래 링크를 참조한다.
https://pyinstaller.org/en/stable/operating-mode.html
This section covers the basic ideas of PyInstaller. These ideas apply to all platforms. Options and special cases are covered below, under Using PyInstaller.
PyInstaller reads a Python script written by you. It analyzes your code to discover every other module and library your script needs in order to execute. Then it collects copies of all those files – including the active Python interpreter! – and puts them with your script in a single folder, or optionally in a single executable file.
For the great majority of programs, this can be done with one short command,
이 섹션에서는 PyInstaller의 기본 아이디어를 다룬다. 이러한 아이디어는 모든 플랫폼에 적용된다. 옵션과 특별한 경우는 아래 PyInstaller 사용에서 다룬다.
PyInstaller는 사용자가 작성한 Python 스크립트를 읽는다. 코드를 분석하여 스크립트를 실행하는 데 필요한 다른 모든 모듈과 라이브러리를 검색한다. 그런 다음 활성 Python 인터프리터를 포함하여 모든 파일의 복사본을 수집한다! – 스크립트와 함께 단일 폴더에 넣거나 선택적으로 단일 실행 파일에 넣는다.
대부분의 프로그램에서 이 작업은 하나의 짧은 명령으로 수행할 수 있다.
pyinstaller myscript.py
or with a few added options, for example a windowed application as a single-file executable,
또는 몇 가지 추가 옵션(예: 단일 파일 실행 파일인 창 응용 프로그램)을 사용하면
pyinstaller --onefile --windowed myscript.py
You distribute the bundle as a folder or file to other people, and they can execute your program. To your users, the app is self-contained. They do not need to install any particular version of Python or any modules. They do not need to have Python installed at all.
번들을 다른 사람에게 폴더나 파일로 배포하면 그들이 프로그램을 실행할 수 있다. 사용자에게 앱은 독립적이다. 특정 버전의 Python이나 모듈을 설치할 필요가 없다. Python을 전혀 설치할 필요가 없다.
Note
The output of PyInstaller is specific to the active operating system and the active version of Python. This means that to prepare a distribution for:
PyInstaller의 출력은 활성 운영 체제 및 Python의 활성 버전에 따라 다르다. 이는 다음을 위한 배포판을 준비한다는 것을 의미한다.
- a different OS
- a different version of Python
- a 32-bit or 64-bit OS
- 다른 OS
- 다른 버전의 Python
- 32비트 또는 64비트 OS
you run PyInstaller on that OS, under that version of Python. The Python interpreter that executes PyInstaller is part of the bundle, and it is specific to the OS and the word size.
해당 OS, 해당 버전의 Python에서 PyInstaller를 실행한다. PyInstaller를 실행하는 Python 인터프리터는 번들의 일부이며 OS 및 word 크기에 따라 다르다.
Analysis: Finding the Files Your Program Needs
What other modules and libraries does your script need in order to run? (These are sometimes called its “dependencies”.)
To find out, PyInstaller finds all the import statements in your script. It finds the imported modules and looks in them for import statements, and so on recursively, until it has a complete list of modules your script may use.
PyInstaller understands the “egg” distribution format often used for Python packages. If your script imports a module from an “egg”, PyInstaller adds the egg and its dependencies to the set of needed files.
PyInstaller also knows about many major Python packages, including the GUI packages Qt (imported via PyQt or PySide), WxPython, TkInter, matplotlib, and other major packages. For a complete list, see Supported Packages.
Some Python scripts import modules in ways that PyInstaller cannot detect: for example, by using the `__import__()` function with variable data, using importlib.import_module(), or manipulating the sys.path value at run time. If your script requires files that PyInstaller does not know about, you must help it:
스크립트를 실행하려면 어떤 다른 모듈과 라이브러리가 필요한가? (이를 "종속성"이라고도 한다.)
이를 확인하기 위해 PyInstaller는 스크립트에서 모든 import 문을 찾는다. 가져온 모듈을 찾고 import 문을 찾는 등의 작업을 반복적으로 수행하여 스크립트에서 사용할 수 있는 전체 모듈 목록을 얻을 수 있다.
PyInstaller는 Python 패키지에 자주 사용되는 “egg” 배포 형식을 이해한다. 스크립트가 “egg”에서 모듈을 가져오는 경우 PyInstaller는 필요한 파일 세트에 egg와 해당 종속성을 추가한다.
PyInstaller는 GUI 패키지 Qt(PyQt 또는 PySide를 통해 가져옴), WxPython, TkInter, matplotlib 및 기타 주요 패키지를 포함하여 많은 주요 Python 패키지에 대해서도 알고 있다. 전체 목록을 보려면 지원되는 패키지를 참조한다.
일부 Python 스크립트는 PyInstaller가 감지할 수 없는 방식으로 모듈을 가져온다. 예를 들어 변수 데이터와 함께 `__import__()` 함수 사용, importlib.import_module() 사용 또는 런타임 시 sys.path 값 조작 등이 있다. 스크립트에 PyInstaller가 알지 못하는 파일이 필요한 경우 도움을 주어야 한다.
- You can give additional files on the pyinstaller command line.
- You can give additional import paths on the command line.
- You can edit the myscript.spec file that PyInstaller writes the first time you run it for your script. In the spec file you can tell PyInstaller about code modules that are unique to your script.
- You can write “hook” files that inform PyInstaller of hidden imports. If you create a “hook” for a package that other users might also use, you can contribute your hook file to PyInstaller.
- pyinstaller 명령줄에서 추가 파일을 제공할 수 있다.
- 명령줄에서 추가 가져오기 경로를 제공할 수 있다.
- PyInstaller가 스크립트에 대해 처음 실행할 때 작성하는 myscript.spec 파일을 편집할 수 있다. 사양 파일에서 스크립트에 고유한 코드 모듈에 대해 PyInstaller에 알릴 수 있다.
- PyInstaller에 숨겨진 가져오기를 알리는 "후크" 파일을 작성할 수 있다. 다른 사용자도 사용할 수 있는 패키지에 대한 "후크"를 생성하면 후크 파일을 PyInstaller에 제공할 수 있다.
If your program depends on access to certain data files, you can tell PyInstaller to include them in the bundle as well. You do this by modifying the spec file, an advanced topic that is covered under Using Spec Files.
In order to locate included files at run time, your program needs to be able to learn its path at run time in a way that works regardless of whether or not it is running from a bundle. This is covered under Run-time Information.
PyInstaller does not include libraries that should exist in any installation of this OS. For example in GNU/Linux, it does not bundle any file from /lib or /usr/lib, assuming these will be found in every system.
프로그램이 특정 데이터 파일에 대한 액세스에 의존하는 경우 PyInstaller에 해당 파일도 번들에 포함하도록 지시할 수 있다. 사양 파일 사용에서 다루는 고급 주제인 사양 파일을 수정하여 이를 수행한다.
런타임에 포함된 파일을 찾으려면 프로그램이 번들에서 실행 중인지 여부에 관계없이 작동하는 방식으로 런타임에 해당 경로를 학습할 수 있어야 한다. 이에 대해서는 런타임 정보에서 다룬다.
PyInstaller에는 이 OS 설치에 존재해야 하는 라이브러리가 포함되어 있지 않다. 예를 들어 GNU/Linux에서는 /lib 또는 /usr/lib의 파일을 번들로 묶지 않는다. 이러한 파일은 모든 시스템에서 발견된다고 가정한다.
Bundling to One Folder
When you apply PyInstaller to myscript.py the default result is a single folder named myscript. This folder contains all your script’s dependencies, and an executable file also named myscript (myscript.exe in Windows).
You compress the folder to myscript.zip and transmit it to your users. They install the program simply by unzipping it. A user runs your app by opening the folder and launching the myscript executable inside it.
It is easy to debug problems that occur when building the app when you use one-folder mode. You can see exactly what files PyInstaller collected into the folder.
Another advantage of a one-folder bundle is that when you change your code, as long as it imports exactly the same set of dependencies, you could send out only the updated myscript executable. That is typically much smaller than the entire folder. (If you change the script so that it imports more or different dependencies, or if the dependencies are upgraded, you must redistribute the whole bundle.)
PyInstaller를 myscript.py에 적용하면 기본 결과는 myscript라는 단일 폴더이다. 이 폴더에는 모든 스크립트의 종속성과 myscript(Windows의 경우 myscript.exe)라는 실행 파일이 포함되어 있다.
폴더를 myscript.zip으로 압축하여 사용자에게 전송한다. 압축을 풀면 프로그램이 설치된다. 사용자는 폴더를 열고 그 안에 있는 myscript 실행 파일을 실행하여 앱을 실행한다.
단일 폴더 모드를 사용하면 앱을 빌드할 때 발생하는 문제를 디버깅하기 쉽다. PyInstaller가 폴더에 수집한 파일이 무엇인지 정확하게 확인할 수 있다.
단일 폴더 번들의 또 다른 장점은 코드를 변경할 때 정확히 동일한 종속성 세트를 가져오는 한 업데이트된 myscript 실행 파일만 보낼 수 있다는 것이다. 이는 일반적으로 전체 폴더보다 훨씬 작다. (더 많거나 다른 종속성을 가져오도록 스크립트를 변경하거나 종속성이 업그레이드되는 경우 전체 번들을 재배포해야 한다.)
How the One-Folder Program Works
A bundled program always starts execution in the PyInstaller bootloader. This is the heart of the myscript executable in the folder.
The PyInstaller bootloader is a binary executable program for the active platform (Windows, GNU/Linux, macOS, etc.). When the user launches your program, it is the bootloader that runs. The bootloader creates a temporary Python environment such that the Python interpreter will find all imported modules and libraries in the myscript folder.
The bootloader starts a copy of the Python interpreter to execute your script. Everything follows normally from there, provided that all the necessary support files were included.
(This is an overview. For more detail, see The Bootstrap Process in Detail below.)
번들 프로그램은 항상 PyInstaller 부트로더에서 실행을 시작한다. 이것이 폴더에 있는 myscript 실행 파일의 핵심이다.
PyInstaller 부트로더는 활성 플랫폼(Windows, GNU/Linux, macOS 등)용 바이너리 실행 프로그램이다. 사용자가 프로그램을 시작할 때 실행되는 것은 부트로더이다. 부트로더는 Python 인터프리터가 myscript 폴더에서 가져온 모든 모듈과 라이브러리를 찾을 수 있도록 임시 Python 환경을 만든다.
부트로더는 스크립트를 실행하기 위해 Python 인터프리터의 복사본을 시작한다. 필요한 모든 지원 파일이 포함되어 있다면 모든 것이 정상적으로 따라온다.
(이것은 간략한 설명이다. 자세한 내용은 부트스트랩 프로세스 세부정보를 참조한다.)
Bundling to One File
PyInstaller can bundle your script and all its dependencies into a single executable named myscript (myscript.exe in Windows).
The advantage is that your users get something they understand, a single executable to launch. A disadvantage is that any related files such as a README must be distributed separately. Also, the single executable is a little slower to start up than the one-folder bundle.
Before you attempt to bundle to one file, make sure your app works correctly when bundled to one folder. It is is much easier to diagnose problems in one-folder mode.
PyInstaller는 스크립트와 모든 종속성을 myscript(Windows의 경우 myscript.exe)라는 단일 실행 파일로 묶을 수 있다.
장점은 사용자가 이해할 수 있는 것, 즉 실행할 단일 실행 파일을 얻을 수 있다는 것이다. 단점은 README와 같은 관련 파일을 별도로 배포해야 한다는 것이다. 또한 단일 실행 파일은 단일 폴더 번들보다 시작 속도가 약간 느리다.
하나의 파일로 묶기를 시도하기 전에 하나의 폴더로 묶었을 때 앱이 올바르게 작동하는지 확인한다. 단일 폴더 모드에서는 문제를 진단하는 것이 훨씬 쉽다.
How the One-File Program Works
The bootloader is the heart of the one-file bundle also. When started it creates a temporary folder in the appropriate temp-folder location for this OS. The folder is named _MEIxxxxxx, where xxxxxx is a random number.
The one executable file contains an embedded archive of all the Python modules used by your script, as well as compressed copies of any non-Python support files (e.g. .so files). The bootloader uncompresses the support files and writes copies into the the temporary folder. This can take a little time. That is why a one-file app is a little slower to start than a one-folder app.
부트로더는 단일 파일 번들의 핵심이기도 하다. 시작되면 이 OS에 적합한 임시 폴더 위치에 임시 폴더가 생성된다. 폴더 이름은 _MEIxxxxxx로 지정되며, 여기서 xxxxxx는 임의의 숫자이다.
하나의 실행 파일에는 스크립트에서 사용하는 모든 Python 모듈의 내장 아카이브와 Python이 아닌 지원 파일(예: .so 파일)의 압축 복사본이 포함되어 있다. 부트로더는 지원 파일의 압축을 풀고 임시 폴더에 복사본을 쓴다. 시간이 조금 걸릴 수 있다. 이것이 단일 파일 앱이 단일 폴더 앱보다 시작하는 데 약간 느린 이유이다.
Note
PyInstaller currently does not preserve file attributes. see #3926.
PyInstaller는 현재 파일 속성을 유지하지 않는다. #3926을 참조한다.
After creating the temporary folder, the bootloader proceeds exactly as for the one-folder bundle, in the context of the temporary folder. When the bundled code terminates, the bootloader deletes the temporary folder.
In GNU/Linux and related systems, it is possible to mount the /tmp folder with a “no-execution” option. That option is not compatible with a PyInstaller one-file bundle. It needs to execute code out of /tmp. If you know the target environment, --runtime-tmpdir might be a workaround. Alternatively, you can set the environment variable that controls the temporary directory before launching the program. See Defining the Extraction Location).
Because the program makes a temporary folder with a unique name, you can run multiple copies of the app; they won’t interfere with each other. However, running multiple copies is expensive in disk space because nothing is shared.
The _MEIxxxxxx folder is not removed if the program crashes or is killed (kill -9 on Unix, killed by the Task Manager on Windows, “Force Quit” on macOS). Thus if your app crashes frequently, your users will lose disk space to multiple _MEIxxxxxx temporary folders.
It is possible to control the location of the _MEIxxxxxx folder by using the --runtime-tmpdir command line option. The specified path is stored in the executable, and the bootloader will create the _MEIxxxxxx folder inside of the specified folder. Please see Defining the Extraction Location for details.
임시 폴더를 생성한 후 부트로더는 임시 폴더의 컨텍스트에서 단일 폴더 번들과 동일하게 진행된다. 번들 코드가 종료되면 부트로더는 임시 폴더를 삭제한다.
GNU/Linux 및 관련 시스템에서는 "실행 없음" 옵션을 사용하여 /tmp 폴더를 마운트할 수 있다. 해당 옵션은 PyInstaller 단일 파일 번들과 호환되지 않는다. /tmp에서 코드를 실행해야 한다. 대상 환경을 알고 있는 경우 --runtime-tmpdir이 해결 방법일 수 있다. 또는 프로그램을 시작하기 전에 임시 디렉터리를 제어하는 환경 변수를 설정할 수 있다.
프로그램은 고유한 이름을 가진 임시 폴더를 만들기 때문에 앱의 여러 복사본을 실행할 수 있다. 그들은 서로 간섭하지 않을 것이다. 그러나 여러 복사본을 실행하면 공유되는 항목이 없기 때문에 디스크 공간이 많이 소모된다.
프로그램이 충돌하거나 종료되는 경우(Unix에서는 kill -9, Windows에서는 작업 관리자에 의해 종료, macOS에서는 "강제 종료") _MEIxxxxxx 폴더가 제거되지 않는다. 따라서 앱이 자주 충돌하면 사용자는 여러 _MEIxxxxxx 임시 폴더에 대한 디스크 공간을 잃게 된다.
--runtime-tmpdir 명령줄 옵션을 사용하여 _MEIxxxxxx 폴더의 위치를 제어할 수 있다. 지정된 경로는 실행 파일에 저장되며 부트로더는 지정된 폴더 내에 _MEIxxxxxx 폴더를 생성한다. 자세한 내용은 추출 위치 정의를 참조한다.
Note
Do not give administrator privileges to a one-file executable on Windows (“Run this program as an administrator”). There is an unlikely but not impossible way in which a malicious attacker could corrupt one of the shared libraries in the temp folder while the bootloader is preparing it. When distributing a privileged program in general, ensure that file permissions prevent shared libraries or executables from being tampered with. Otherwise, an unelevated process which has write access to these files may escalate privileges by modifying them.
Windows에서 단일 파일 실행 파일에 관리자 권한을 부여하지 않아야 한다("관리자 권한으로 이 프로그램 실행"). 부트로더가 준비하는 동안 악의적인 공격자가 임시 폴더에 있는 공유 라이브러리 중 하나를 손상시킬 수 있는 가능성은 낮지만 불가능하지는 않다. 일반적으로 권한 있는 프로그램을 배포할 때 파일 권한이 공유 라이브러리나 실행 파일이 변조되는 것을 방지하는지 확인한다. 그렇지 않으면 이러한 파일에 대한 쓰기 액세스 권한이 있는 권한이 없는 프로세스가 해당 파일을 수정하여 권한을 상승시킬 수 있다.
Note
Applications that use os.setuid() may encounter permissions errors. The temporary folder where the bundled app runs may not being readable after setuid is called. If your script needs to call setuid, it may be better to use one-folder mode so as to have more control over the permissions on its files.
os.setuid()를 사용하는 애플리케이션에서는 권한 오류가 발생할 수 있다. setuid가 호출된 후 번들 앱이 실행되는 임시 폴더를 읽지 못할 수 있다. 스크립트에서 setuid를 호출해야 하는 경우 해당 파일에 대한 권한을 더 효과적으로 제어할 수 있도록 단일 폴더 모드를 사용하는 것이 더 나을 수 있다.
Using a Console Window
By default the bootloader creates a command-line console (a terminal window in GNU/Linux and macOS, a command window in Windows). It gives this window to the Python interpreter for its standard input and output. Your script’s use of print and input() are directed here. Error messages from Python and default logging output also appear in the console window.
An option for Windows and macOS is to tell PyInstaller to not provide a console window. The bootloader starts Python with no target for standard output or input. Do this when your script has a graphical interface for user input and can properly report its own diagnostics.
As noted in the CPython tutorial Appendix, for Windows a file extension of .pyw suppresses the console window that normally appears. Likewise, a console window will not be provided when using a myscript.pyw script with PyInstaller.
기본적으로 부트로더는 명령줄 콘솔(GNU/Linux 및 macOS의 터미널 창, Windows의 명령 창)을 생성한다. 표준 입력 및 출력을 위해 Python 인터프리터에 이 창을 제공한다. 스크립트의 print 및 input() 사용은 여기로 지정된다. Python의 오류 메시지와 기본 로깅 출력도 콘솔 창에 나타난다.
Windows 및 macOS의 옵션은 PyInstaller에 콘솔 창을 제공하지 않도록 지시하는 것이다. 부트로더는 표준 출력이나 입력에 대한 대상 없이 Python을 시작한다. 스크립트에 사용자 입력을 위한 그래픽 인터페이스가 있고 자체 진단을 적절하게 보고할 수 있는 경우 이를 수행한다.
CPython 튜토리얼 부록에서 언급했듯이 Windows의 경우 .pyw 파일 확장자는 일반적으로 나타나는 콘솔 창을 억제한다. 마찬가지로, PyInstaller와 함께 myscript.pyw 스크립트를 사용하는 경우 콘솔 창이 제공되지 않는다.
Hiding the Source Code
The bundled app does not include any source code. However, PyInstaller bundles compiled Python scripts (.pyc files). These could in principle be decompiled to reveal the logic of your code.
If you want to hide your source code more thoroughly, one possible option is to compile some of your modules with Cython. Using Cython you can convert Python modules into C and compile the C to machine language. PyInstaller can follow import statements that refer to Cython C object modules and bundle them.
번들 앱에는 소스 코드가 포함되어 있지 않다. 그러나 PyInstaller는 컴파일된 Python 스크립트(.pyc 파일)를 번들로 묶는다. 원칙적으로 이러한 코드는 디컴파일되어 코드의 논리를 드러낼 수 있다.
소스 코드를 더 철저하게 숨기려면 가능한 옵션 중 하나는 Cython을 사용하여 일부 모듈을 컴파일하는 것이다. Cython을 사용하면 Python 모듈을 C로 변환하고 C를 기계어로 컴파일할 수 있다. PyInstaller는 Cython C 개체 모듈을 참조하고 이를 번들로 묶는 import 문을 따를 수 있다.
728x90'코딩 > Python' 카테고리의 다른 글
Python/지도를 사용할 수 있는 Folium/0. Getting started (0) 2024.07.09 Python/PyInstaller/0. PyInstaller Manual (0) 2024.07.08 Python/PyInstaller/2. Using PyInstaller (0) 2024.07.08 Python/PyInstaller 사용법 (0) 2024.07.08 Python/python-pptx 사용자 가이드 (0) 2024.06.12