Cara menggunakan PyInstaller untuk membuat file executable Python

Python, kuat dan serbaguna, tidak memiliki beberapa kemampuan utama di luar kotak. Pertama, Python tidak menyediakan mekanisme asli untuk mengompilasi program Python menjadi paket yang dapat dijalankan secara mandiri.

Agar adil, kasus penggunaan asli untuk Python tidak pernah memanggil paket mandiri. Program Python pada umumnya telah dijalankan di tempat pada sistem tempat salinan interpreter Python berada. Tetapi popularitas Python yang melonjak telah menciptakan permintaan yang lebih besar untuk menjalankan aplikasi Python pada sistem tanpa runtime Python yang diinstal.

Beberapa pihak ketiga telah merekayasa solusi untuk menerapkan aplikasi Python mandiri. Solusi paling populer dari kelompok tersebut, dan yang paling matang, adalah PyInstaller. PyInstaller tidak membuat proses pengemasan aplikasi Python menjadi tanpa rasa sakit sama sekali, tetapi prosesnya sangat panjang.

Dalam artikel ini kita akan menjelajahi dasar-dasar penggunaan PyInstaller termasuk cara kerja PyInstaller, cara menggunakan PyInstaller untuk membuat Python mandiri yang dapat dieksekusi, cara menyempurnakan executable Python yang Anda buat, dan cara menghindari beberapa perangkap umum yang terjadi. dengan menggunakan PyInstaller.

Membuat paket PyInstaller

PyInstaller adalah paket Python, diinstal dengan pip( pip install pyinstaller). PyInstaller dapat diinstal di instalasi Python default Anda, tetapi yang terbaik adalah membuat lingkungan virtual untuk proyek yang ingin Anda paketkan dan instal PyInstaller di sana.

PyInstaller bekerja dengan membaca program Python Anda, menganalisis semua impor yang dibuatnya, dan menggabungkan salinan impor tersebut dengan program Anda. PyInstaller membaca program Anda dari titik masuknya. Misalnya, jika titik masuk program Anda adalah myapp.py, Anda akan menjalankan pyinstaller myapp.pyuntuk melakukan analisis. PyInstaller dapat mendeteksi dan secara otomatis mengemas banyak paket Python umum, seperti NumPy, tetapi Anda mungkin perlu memberikan petunjuk dalam beberapa kasus. (Lebih lanjut tentang ini nanti.)

Setelah menganalisis kode Anda dan menemukan semua pustaka dan modul yang digunakannya, PyInstaller kemudian membuat "file spesifikasi". Skrip Python dengan ekstensi .spec, file ini menyertakan detail tentang bagaimana aplikasi Python Anda perlu dikemas. Pertama kali Anda menjalankan PyInstaller di aplikasi Anda, PyInstaller akan membuat file spesifikasi dari awal dan mengisinya dengan beberapa default yang wajar. Jangan buang file ini; itu kunci untuk menyempurnakan penerapan PyInstaller!

Terakhir, PyInstaller mencoba menghasilkan file yang dapat dieksekusi dari aplikasi, dipaketkan dengan semua dependensinya. Setelah selesai, subfolder bernama dist (secara default; Anda bebas menentukan nama lain) akan muncul di direktori proyek. Ini pada gilirannya berisi direktori yang merupakan aplikasi paket Anda - ia memiliki .exefile untuk dijalankan, bersama dengan semua pustaka dan file tambahan lain yang diperlukan.

Yang perlu Anda lakukan untuk mendistribusikan program Anda adalah mengemas direktori ini sebagai .zipfile atau bundel lainnya. Paket tersebut biasanya perlu diekstrak di direktori tempat pengguna memiliki izin menulis untuk menjalankannya.

Menguji paket PyInstaller

Ada kemungkinan besar upaya pertama Anda menggunakan PyInstaller untuk mengemas aplikasi tidak akan sepenuhnya berhasil.

Untuk memeriksa apakah paket PyInstaller Anda berfungsi, navigasikan ke direktori yang berisi paket yang dapat dieksekusi dan jalankan .exefile di sana dari baris perintah. Jika gagal dijalankan, kesalahan yang akan Anda lihat dicetak ke baris perintah seharusnya memberikan petunjuk tentang apa yang salah.

Alasan paling umum mengapa paket PyInstaller gagal adalah karena PyInstaller gagal menggabungkan file yang diperlukan. File yang hilang tersebut termasuk dalam beberapa kategori:

  • Impor tersembunyi atau hilang : Terkadang PyInstaller tidak dapat mendeteksi impor paket atau pustaka, biasanya karena diimpor secara dinamis. Paket atau pustaka perlu ditentukan secara manual.
  • File mandiri yang hilang : Jika program bergantung pada file data eksternal yang perlu digabungkan dengan program, PyInstaller tidak dapat mengetahuinya. Anda harus memasukkan file secara manual.
  • Biner yang hilang : Di sini sekali lagi, jika program Anda bergantung pada biner eksternal seperti .DLL yang tidak dapat dideteksi PyInstaller, Anda harus memasukkannya secara manual.

Kabar baiknya adalah PyInstaller menyediakan cara mudah untuk mengatasi masalah di atas. The .specfile yang dibuat oleh PyInstaller termasuk bidang yang kita dapat mengisi untuk memberikan rincian yang PyInstaller terjawab.

Buka .specfile di editor teks dan cari definisi Analysisobjek. Beberapa parameter yang diteruskan ke Analysisadalah daftar kosong, tetapi mereka dapat diedit untuk menentukan detail yang hilang:

  • hiddenimportsuntuk impor yang tersembunyi atau hilang : Tambahkan ke daftar ini satu atau beberapa string dengan nama pustaka yang ingin Anda sertakan dengan aplikasi Anda. Jika Anda ingin menambahkan pandasdan bokeh, misalnya, Anda akan menetapkannya sebagai  ['pandas','bokeh']. Perhatikan bahwa pustaka yang dimaksud harus diinstal dalam instance Python yang sama di mana Anda menjalankan PyInstaller.
  • datasuntuk file mandiri yang hilang : Tambahkan di sini satu atau beberapa spesifikasi untuk file di pohon proyek Anda yang ingin Anda sertakan dengan proyek Anda. Setiap file harus diteruskan sebagai tupel yang menunjukkan jalur relatif ke file dalam direktori proyek Anda dan jalur relatif dalam direktori distribusi tempat Anda ingin meletakkan file. Misalnya, jika Anda memiliki file ./models/mainmodel.datyang ingin Anda sertakan dengan aplikasi Anda, dan Anda ingin menempatkannya di subdirektori yang cocok dalam direktori distribusi Anda, Anda akan menggunakan ('./models/mainmodel.dat','./models')sebagai satu entri dalam hiddenimportsdaftar. Perhatikan bahwa Anda dapat menggunakan karakter globpengganti gaya untuk menentukan lebih dari satu file.
  • binariesuntuk binari mandiri yang hilang : Seperti halnya datas, Anda dapat menggunakan binariesuntuk meneruskan daftar tupel yang menentukan lokasi biner di pohon proyek dan tujuannya di direktori distribusi. Sekali lagi, Anda dapat menggunakan karakter globpengganti gaya.

Ingatlah bahwa salah satu daftar yang diteruskan ke Analysisdapat dibuat secara terprogram lebih awal dalam .specfile. Bagaimanapun, .specfile tersebut hanyalah skrip Python dengan nama lain.

Setelah Anda membuat perubahan pada .specfile, jalankan kembali PyInstaller untuk membangun kembali paket. Namun, mulai sekarang, pastikan untuk meneruskan .specfile yang dimodifikasi sebagai parameter (mis pyinstaller myapp.spec.). Uji yang dapat dieksekusi seperti sebelumnya. Jika masih ada yang rusak, Anda dapat mengedit ulang .specfile tersebut dan mengulangi prosesnya hingga semuanya berfungsi.

Terakhir, setelah Anda puas semuanya berfungsi sebagaimana mestinya, Anda mungkin ingin mengedit  .specfile untuk mencegah aplikasi terpaket Anda menampilkan jendela baris perintah saat diluncurkan. Dalam EXEpengaturan objek di .specfile, set  console=False. Menekan konsol berguna jika aplikasi Anda memiliki GUI dan Anda tidak ingin jendela baris perintah palsu menyesatkan pengguna. Tentu saja, jangan ubah setelan ini jika aplikasi Anda memerlukan baris perintah.

Menyempurnakan paket PyInstaller

Setelah aplikasi Anda dikemas dengan PyInstaller dan berjalan dengan benar, hal berikutnya yang mungkin ingin Anda lakukan adalah sedikit merampingkannya. Paket PyInstaller tidak dikenal sebagai paket yang langsing.

Karena Python adalah bahasa dinamis, sulit untuk memprediksi apa yang akan dibutuhkan saat runtime oleh program tertentu. Oleh karena itu, ketika PyInstaller mendeteksi impor paket, itu menyertakan semua yang ada dalam paket itu, apakah itu benar-benar digunakan saat runtime oleh program Anda atau tidak. 

Inilah kabar baiknya. PyInstaller menyertakan mekanisme untuk mengecualikan seluruh paket secara selektif, atau ruang nama individu dalam paket. Misalnya, program Anda mengimpor paket foo, yang menyertakan foo.bardan foo.bip. Jika Anda mengetahui fakta bahwa program Anda hanya menggunakan logika foo.bar, Anda dapat dengan aman mengecualikan foo.bip dan menghemat ruang.

Untuk melakukan ini, Anda menggunakan excludesparameter yang diteruskan ke Analysisobjek di .specfile. Anda dapat memberikan daftar nama - modul tingkat atas, atau ruang nama bertitik - untuk dikecualikan dari paket Anda. Misalnya, untuk mengecualikan foo.bip, Anda cukup menentukan  ['foo.bip'].

Satu pengecualian umum yang dapat Anda buat adalah tkinter, pustaka Python untuk membuat antarmuka pengguna grafis lintas platform sederhana. Secara default,  tkinterdan semua file dukungannya dikemas dengan proyek PyInstaller. Jika Anda tidak menggunakan tkinterdalam proyek Anda, Anda dapat mengecualikannya dengan menambahkan 'tkinter'ke excludesdaftar. Menghilangkan tkinterakan mengurangi ukuran paket sekitar 7 MB.

Pengecualian umum lainnya adalah rangkaian pengujian. Jika sebuah paket yang diimpor oleh program Anda memiliki rangkaian pengujian, rangkaian pengujian tersebut mungkin akan disertakan dalam paket PyInstaller Anda. Kecuali jika Anda benar-benar menjalankan rangkaian pengujian dalam program yang Anda terapkan, Anda dapat mengecualikannya dengan aman.

Ingatlah bahwa paket yang dibuat menggunakan pengecualian harus diuji secara menyeluruh sebelum digunakan. Jika Anda akhirnya mengecualikan fungsionalitas yang digunakan dalam beberapa skenario masa depan yang tidak Anda antisipasi, aplikasi Anda akan rusak.

Kiat PyInstaller

  • Buat paket PyInstaller Anda di OS yang Anda rencanakan untuk digunakan.  PyInstaller tidak mendukung pembuatan lintas platform. Jika Anda perlu menerapkan aplikasi Python mandiri di sistem MacOS, Linux, dan Windows, Anda perlu menginstal PyInstaller dan membuat versi aplikasi terpisah di masing-masing sistem operasi ini. 
  • Buat paket PyInstaller Anda saat Anda mengembangkan aplikasi.  Segera setelah Anda tahu bahwa Anda akan menerapkan proyek Anda dengan PyInstaller, buat .specfile Anda dan mulailah menyempurnakan paket PyInstaller secara paralel dengan pengembangan aplikasi Anda. Dengan cara ini Anda dapat menambahkan pengecualian atau inklusi saat Anda pergi, dan menguji cara fitur baru diterapkan dengan aplikasi saat Anda menulisnya.
  • Jangan gunakan --onefilemode PyInstaller  .  PyInstaller menyertakan sakelar baris perintah --onefile,, yang mengemas seluruh aplikasi Anda menjadi satu file yang dapat diekstrak sendiri. Ini sepertinya ide yang bagus - Anda hanya perlu mengirimkan satu file! - tapi ada beberapa jebakan. Setiap kali Anda menjalankan aplikasi, pertama-tama aplikasi harus membongkar semua file dalam file yang dapat dieksekusi ke direktori sementara. Jika aplikasinya besar (200MB, misalnya), pembongkaran dapat berarti penundaan selama beberapa detik. Gunakan mode direktori tunggal default sebagai gantinya, dan cukup kemas semuanya sebagai .zipfile.
  • Buat penginstal untuk aplikasi PyInstaller Anda.  Jika Anda ingin beberapa cara untuk menerapkan aplikasi Anda selain file .zip, pertimbangkan untuk menggunakan utilitas penginstal seperti Nullsoft Scriptable Install System open source. Ini menambahkan sedikit overhead ke ukuran pengiriman dan memungkinkan Anda mengonfigurasi banyak aspek proses instalasi, seperti membuat pintasan ke file yang dapat dieksekusi.
  • Jangan berharap percepatan.  PyInstaller adalah  sistem pengemasan , bukan  kompiler  atau  pengoptimal . Kode yang dikemas dengan PyInstaller tidak berjalan lebih cepat daripada saat dijalankan di sistem asli. Jika Anda ingin mempercepat kode Python, gunakan pustaka C-accelerated yang cocok untuk tugas tersebut, atau proyek seperti Cython.

Bagaimana melakukan lebih banyak hal dengan Python

  • Tutorial Cython: Cara mempercepat Python
  • Cara menginstal Python dengan cara cerdas
  • Manajemen proyek Python yang lebih baik dengan Poetry
  • Virtualenv dan venv: Penjelasan lingkungan virtual Python
  • Python virtualenv dan venv lakukan dan tidak boleh dilakukan
  • Penjelasan threading dan subproses Python
  • Cara menggunakan debugger Python
  • Cara menggunakan timeit untuk membuat profil kode Python
  • Cara menggunakan cProfile untuk membuat profil kode Python
  • Mulailah dengan async dengan Python
  • Cara menggunakan asyncio dengan Python
  • Cara mengonversi Python ke JavaScript (dan kembali lagi)