SKCONAN

แปลงไฟล์ Python เป็น .exe ด้วย Pyinstaller (พร้อมยกตัวอย่างปัญหา)

January 26, 2019

title

Pyinstaller

PyInstaller freezes (packages) Python applications into stand-alone executables, under Windows, GNU/Linux, Mac OS X, FreeBSD, Solaris and AIX.

Pyinstaller คือ module หรือเครื่องมือที่ช่วยแปลงโปรแกรมที่เขียนด้วยภาษา python (ไฟล์.py) ให้สามารถไป run บนเครื่องคอมพิวเตอร์เครื่องอื่นๆได้แบบ stand-alone โดยเจ้าตัว pyinstaller มันสามารถ run ได้ทั้งบน windows, linux, และ mac ซึ่งสนับสนุน python 2.7 และ python 3.4 - 3.7

ในบทความนี้จะพูดถึงการแปลงไฟล์ .py ไปเป็น .exe สำหรับ run บนระบบปฏิบัติการ windows 10 64 bit นะครับ เนื่องจากว่า tensorflow สามารถติดตั้งได้เฉพาะบน windows 64 bit เท่านั้น ทำให้โปรแกรม (.exe) ที่แปลงมาจาก python นั้นใช้งานได้เฉพาะบน Windows 8 และ 10 ที่เป็น 64 bit เท่านั้น


เตรียมตัวก่อนใช้ pyinstaller

  • แนะนำให้ใช้ virtualenv การติดตั้ง Python และ Virtualenv บน Windows 10 เพื่อที่จะได้จัดการกับ libraries หรือ module ได้ง่าย
  • ถ้าหากมีการเรียกไฟล์ หรืออ้างอิง PATH ภายในโปรแกรมแนะนำให้เขียน PATH แบบ relative path เช่น อ้างอิงจาก os.path.abspath(file)
  • สำหรับเครื่องใครยังไม่มี Windows 10 SDK แนะนำให้ติดตั้งก่อนนะครับ เพราะตัว Python 3 จะใช้ตัว DLLs ของ Windows SDK หลังจากนั้นให้เพิ่ม PATH C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\ เข้าไปที่ Environment variables ของ System ด้วยนะครับ ถ้าไม่ติดตั้งจะขึ้น WARNING ตามด้านล่างนี้นะครับ และก็อาจจะทำให้ไฟล์ .exe ขอเราไม่สามารถใช้งานได้
6637 WARNING: lib not found: api-ms-win-crt-math-l1-1-0.dll dependency of c:\users\skconan\appdata\local\programs\python\python36\python.exe
6654 WARNING: lib not found: api-ms-win-crt-stdio-l1-1-0.dll dependency of c:\users\skconan\appdata\local\programs\python\python36\python.exe
6683 WARNING: lib not found: api-ms-win-crt-locale-l1-1-0.dll dependency of c:\users\skconan\appdata\local\programs\python\python36\python.exe
...


## ติดตั้ง pyinstaller

เราจะติดตั้งผ่าน Pip นะครับ ใครไม่สามารถใช้งาน Pip ได้ให้ลองดูอันนี้ก่อนครับ VS Code, Python - มาเขียน Python บน Visual Studio Code กันครับ

ให้สั่ง

 pip install pyinstaller



Compile .py to .exe

เราต้องมีไฟล์ GUI หลักของเราก่อน โดยจะขอยกตัวอย่างมาจากโปรเจคที่ผมทำอยู่นะครับ ของผมจะใช้ Tkinter ในการสร้าง GUI นะครับก็ประมาณนี้

ตัวอย่าง ไฟล์ GUI

# Filename: braille_gui.py
import tkinter as tk

class BrailleTranslatorApp(tk.Tk):
"""
    My program
"""

app = BrailleTranslatorApp()
app.mainloop()

ต่อมาเราก็จะ run คำสั่ง pyinstaller <file_name.py>

    pyinstaller ./braille_gui.py

แล้วเราก็จะได้ folder build กับ dist ให้เราเข้าไปดูใน folder dist ไฟล์ .exe ของเราจะอยู่ในนั้น ก็เสร็จเรียบร้อยแล้วนะครับ


dir 0

เพิ่มเติม

  • ถ้าใครมีการใช้ File รูปภาพ หรือไฟล์ต่างๆ ต้องแก้ไขไฟล์ braille_gui.spec โดยเพิ่ม PATH ของไฟล์ต่างๆ ไปตรง datas

    ไม่เช่นนั้น ตอนรันไฟล์ .exe เพื่อใช้งานจะเกิดปัญหา หาไฟล์ไม่เจอ เช่น ในไฟล์ gui.py มีการเรียกใช้ไฟล์ test.jpg ก็ให้เราเข้าไปแก้ในไฟล์ gui.spec ดังตัวอย่างข้างล่าง

  • โดยเวลาแก้ให้แก้ตามนี้ (‘Source path’, ‘Destination path’)

    Source path คือ ไฟล์ของเรา เช่น test.jpg

    Destination path คือ folder ปลายทางโดยให้ใช้เป็น relative path จะเริ่มนับจาก folder ที่มี braille_gui.exe ก็คือ dist/braille_gui/

dir tree 0
# -*- mode: python -*-

block_cipher = None

a = Analysis(['source\\gui.py'],
             pathex=['C:\\Users\\skconan\\Desktop\\braille'],
             binaries=[],
             datas=[
                 ('.\\images\\test.jpg','images\\'),
             ],

  • ลองรัน script ใหม่ให้ใช้คำสั่ง
    pyinstaller ./braille_gui.spec

  • เราก็จะเห็น folder images อยู่ใน dist/braille_gui
dir tree 1
  • ถ้ามีไฟล์อื่นอีกก็เพิ่มเข้าไป โดยเพิ่ม tuple (‘Source path’,‘Destination path’) เข้าไปใน list ของ datas แล้วก็รันคำสั่งเดิมใหม่ เท่านี้เราก็จะได้ไฟล์โรปรแกรมของเราที่เป็น .exe แล้วครับ

  • ถ้าต้องการนำโปรแกรมของเราไปทดสอบที่เครื่องอื่น ก็ให้ copy ไปทั้ง folder dist


ปัญหาที่พบ

สำหรับใครที่ใช้ library nltk จะมีปัญหาอยู่ 2-3 อย่างมาดูปัญหาที่ผมเจอ แล้วก็วิธีแก้กัน

  1. ปัญหานี้คิดว่าทุกคนน่าจะเจอเหมือนกัน คือ error ฟ้องว่าหาไฟล์ pyi_rth_nltk.py ไม่เจอ ก็ให้เราไปที่ <folder environment ของเรา>\Lib\site-packages\PyInstaller\loader\rthooks\ แล้วหา pyi_rth__nltk.py (underscore 2 อันตรง rth กับ nltk) แล้วก็ rename ก็หมดปัญหาแล้วครับ
FileNotFoundError: [Errno 2] No such file or directory: 'c:\\users\\skconan\\desktop\\braille\\env\\lib\\site-packages\\PyInstaller\\loader\\rthooks\\pyi_rth_nltk.py'

  1. สำหรับคนที่มีการ download ไฟล์ word หรือไฟล์ต่างๆของ nltk มาใช้ pyinstaller จะฟ้องว่าหาไฟล์ nltk_data ไม่เจอ ถึงแม้เราจะ copy folder nltk_data มาวางไว้ตรงที่ error ขึ้นแล้วก็ตามมันก็จะยังคงขึ้นว่าไม่พบ nltk_data ที่ใหม่อีก

    เช่น ตอนแรกมันบอกไม่มี nltk_data ที่ C:\Users\skconan\nlkt_data พอเรา copy มาวางมันก็จะขึ้น error ที่อื่นมาอีก

    ซึ่งเกิดจากที่ไฟล์ hook-nltk.py มัน append data path ไว้หลายที่ ให้เราเข้าไปแก้ที่ <folder environment ของเรา>\Lib\site-packages\PyInstaller\hooks\hook-nltk.py โดยแก้ให้มัน append แค่ path ที่ไฟล์ nltk_data อยู่ก็พอส่วนมาก folder nltk_data จะอยู่ที่ C:\\Users\\skconan\\AppData\\Roaming\\nltk_data ก็ให้แก้โค้ดตามด้านล่างเลยครับ

# hook for nltk
import nltk
from PyInstaller.utils.hooks import collect_data_files

# add datas for nltk
datas = collect_data_files('nltk', False)

# loop through the data directories and add them
datas.append(("C:\\Users\\skconan\\AppData\\Roaming\\nltk_data", "nltk_data"))

# nltk.chunk.named_entity should be included
hiddenimports = ["nltk.chunk.named_entity"]

  1. แล้วก็ระวังเรื่อง version ของ numpy ด้วยนะครับ อ้างอิงจาก issue นี้ครับ

  2. ต้องลง Library ที่ชื่อว่า tornado ผมไม่แน่ใจนะครับว่า Library นี้ใช้ทำอะไร แต่ของผมมันขึ้นว่า

ModuleNotFoundError: No module named 'tornado'

ก็เลยลงเพิ่มไปครับ

ข้อจำกัด

  • ระบบปฏิบัติการ - หากใช้ระบบปฏิบัติการ Windows 10 ตัว executable ไฟล์ที่ออกมาสามารถจะใช้ได้เฉพาะบน windows 8 และ 10 เท่านั้น ถ้าอยากให้ใช้บน Windows 7 ได้ ก็ให้ไปรัน script บน windows 7

  • Library - ไม่สามารถ compile library 64 bit เพื่อไปรันบน windows 32 bit


บทความนี้ก็เป็นตัวอย่างการแปลงโปรแกรม python เป็น executable file ในบทความหน้าจะมาสอนวิธีสร้างไฟล์ installation โดยใช้ Inno Setup Compiler

หากใครชอบเนื้อหาที่ผมเขียน สามารถร่วมกัน Donate เพื่อเป็นค่ากาแฟได้นะครับ ^^


ใครที่สงสัยจุดไหน หรือพบว่าจุดไหนที่ผมอธิบายผิด สามารถเข้ามาพูดคุยกันได้นะครับ inbox มาที่ Facebook, Twitter เลยก็ได้ครับ หรือ mail มาที่ supakit.kr@gmail.com จะยินดีมากเลยครับ



Written by Supakit Kriangkhajorn

© 2019, Built with