When you want to pass a Python script to another person, it is troublesome to build an environment on the other person's PC. I would like to make it an executable file if possible. Pyinstaller and Nuitka are useful modules to achieve this. The latter is said to have the characteristics that the size of the executable file is small and the execution speed is fast after converting to C and then compiling.
After compiling Nuitka, it can be troublesome to run it and fix it if you get an Import Error (also Pyinstaller). Therefore, using the hinted-compilation of NUITKA-Utilities, run the Python script once to understand the module used, and then compile it to reduce failures. It was very easy to use and convenient, so I would like to introduce it with a comparison with Pyinstaller.
I found out about NUITKA-Utilities here. Please refer to here for how to use scripts other than hinted-compilation. Qiita: Easy Python compilation with NUITKA-Utilities
Download NUITKA-Utilities. GitHub: NUITKA-Utilities Install nuitka, pysimplegui, and MinGW in advance. In the case of Anaconda environment, it is as follows.
conda install -c conda-forge nuitka
conda install -c conda-forge pysimplegui
Installing MinGW is a bit tricky and should be matched with the installed Python architecture. Type Python at the command prompt to confirm.
C:\>python
Python 3.7.4 (default, Aug 9 2019, 18:34:13) [MSC v.1915 64 bit (AMD64)] :: Anaconda,
Inc. on win32
Install MinGW by referring to Let's Programming: Downloading and installing MinGW-w64. In the above example, Python is 64bit, so change the MinGW installer Architecture to x86_x64.
Make sure your PATH is correct.
C:\>gcc --version
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
If you do not want to set the PATH because there is another version originally, you can execute mingw-w64.bat where MinGW is installed.
For the sake of explanation, name the script file you want to compile as yourscript.py.
Go to the NUITKA-Utilities \ hinted-compilation directory and run the script as shown below. The script will be executed and the used module will be written to the json file.
python get-hints.py yourscript.py
Then run the script as follows: At this time, put yourscript.py and the previous json file in the same hierarchy.
python nuitka-hints.py yourscript.py
With just this, you can create an executable file from a Python script file. If you want to combine the files into one, use onefile-maker-windows.py.
I wrote the code based on the problem that appeared in SPI3. Using this as an example, measure the execution speed and startup speed.
import numpy as np
import time
def coin_prob(N=1000000):
"""
Throw 1 10-yen coin, 2 5-yen coins, 5 1-yen coins,
Add the amount of coins on the table.
What is the probability of becoming 15 yen?
"""
coins = np.array([10,5,5,1,1,1,1,1])
count=0
for _ in range(N):
heads_or_tails = np.random.randint(0,2,len(coins)) #0 or 1
if np.sum(coins*heads_or_tails) == 15:
count += 1
print("The probability is{}".format(count/N))
def main():
"""
Find the mean time and standard deviation of 10 times.
"""
elapsed_times = []
for _ in range(10):
start = time.time()
coin_prob()
end = time.time()
elapsed_times.append(end-start)
ave_time = np.average(elapsed_times)
std_time = np.std(elapsed_times)
print("processing time={0}±{1}".format(ave_time,std_time))
if __name__ == "__main__":
start_all = time.time()
main()
end_all = time.time()
print("Total elapsed time{}".format(end_all-start_all))
Neither Pyinstaller nor Nuitka have the option to combine them into one file.
As an aside, both Pyinstaller and Nuitka didn't go smoothly and suffered a little. Pyinstaller solved it by referring to this article. Avoid run-time error ModuleNotFoundError for executables generated from Python code using Qiita: Pyinstaller Nuitka did not go well with mkl and solved it here. Notes on Nuupan: What to do if mkl fails to load under the conda environment
In the beginning, Nuitka said the file size was small, but it wasn't. I hope it will continue to be improved and will not import extra modules.
Original | Pyinstaller | Nuitka |
---|---|---|
1.02KB | 569MB | 623MB |
The average and standard deviation of 10 coin-throwing trials are shown as the processing time for one set. It's not the point, but I also included Numba jit for comparison. If you want speedup, you should use this.
Original | Pyinstaller | Nuitka | Numba jit | |
---|---|---|---|---|
Time s | 18.44±0.54 | 18.30±0.26 | 4.275±0.076 | 0.2299±0.1281 |
Gain | 1.000 | 1.008 | 4.314 | 80.21 |
The time from the start to the end of the program was measured with timeit.exe of Windows Server 2003 Resource Kit Tools, and the difference from the processing time of the main function inside the program was measured three times.
Original | Pyinstaller | Nuitka | |
---|---|---|---|
Time ms | 213.3±2.8 | 235.8±2.2 | 88.39±1.72 |
Gain | 1.000 | 0.905 | 2.414 |
Except for the file size, it outperformed Pyinstaller in terms of execution speed and startup speed. It is recommended because it has fewer errors and is easier than Pyinstaller.
Recommended Posts