Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use PyInstaller from script, not terminal?

Short version:

How do I use PyInstaller from within a Python script, instead of from the terminal?

What would I need to write inside a Python script to get the equivalent of writing this in the terminal:

>python -m PyInstaller --noconsole --name WorkLogger ../WorkLogger/main.py

Long version:

I'm using a library that requires using PyInstaller to distribute an executable. But I have to run PyInstaller once, then change the spec files, then run the spec file through PyInstaller.

So in the terminal I would've done this:

>python -m PyInstaller --noconsole --name WorkLogger ../WorkLogger/main.py

After this is done running, I manually change the spec file. Then I run:

>python -m PyInstaller WorkLogger.spec

I've written a script that does the manual labor for me, by running

>change_spec.py

But I ultimately want to do all of this in one Python script. I want to be able to type something like this:

>distribute_python_project.py ./Worklogger

This means my Python script would need to look something like this:

#Psuedocode:
#python -m PyInstaller --noconsole --name WorkLogger ../WorkLogger/main.py
#Code from change_spec.py
#python -m PyInstaller WorkLogger.spec

But I can't figure out how I use PyInstaller from a python script, instead of from the terminal. Is this possible? (The library I use is Kivy, for those interested).

like image 392
Einar Avatar asked Oct 03 '18 22:10

Einar


3 Answers

Berniiiii's answer was correct but not straight to the point and I personally found it a bit confusing.

this is an answer from the official docs: running-pyinstaller-from-python-code

import PyInstaller.__main__

PyInstaller.__main__.run([
    'my_script.py',
    '--onefile',
    '--windowed'
])

Is equivalent to:

pyinstaller my_script.py --onefile --windowed
like image 190
coder Avatar answered Nov 11 '22 00:11

coder


Thanks to Employee and Canh! Working proof of concept:

Terminal:

>python -m PyInstaller --noconsole --name WorkLogger ../WorkLogger/main.py

Python script:

subprocess.call(r"python -m PyInstaller --noconsole --name WorkLogger F:\KivyApps\WorkLogger\main.py")

If needed, you can start the subprocess from a specific working directory:

subprocess.call(r"python -m PyInstaller --noconsole --name WorkLogger F:\KivyApps\WorkLogger\main.py", cwd=r"F:\KivyApps\WorkLogger_Dist")
like image 5
Einar Avatar answered Nov 10 '22 23:11

Einar


You can even access directly to PyInstaller's module using spec file if you want. In this example this with different locations of spec-file, dist-dir and build-dir.

import PyInstaller

# my spec file in "dev\config" dir
workdir = os.getcwd()
fn_msi_spec = os.path.join(workdir, 'main_msi.spec')

# define the "dev\dist" and "dev\build" dirs
os.chdir("..")
devdir = os.getcwd()
distdir = os.path.join(devdir, 'dist')
builddir = os.path.join(devdir, 'build')

# call pyinstaller directly
PyInstaller.__main__.run(['--distpath', distdir, '--workpath', builddir, fn_msi_spec])
like image 4
Berniiiii Avatar answered Nov 10 '22 23:11

Berniiiii