Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python API breaks when creating executable with pyinstaller #3501

Closed
1 of 2 tasks
teiserse opened this issue Jan 21, 2021 · 2 comments
Closed
1 of 2 tasks

Python API breaks when creating executable with pyinstaller #3501

teiserse opened this issue Jan 21, 2021 · 2 comments
Labels
duplicate This issue or pull request already exists out of scope question

Comments

@teiserse
Copy link

Issue

  • This is not a bug report, feature request, or plugin issue/request.
  • I have read the contribution guidelines.

Description

The main streamlink.streams() function works when used in a script, but breaks when it is compiled using pyinstaller.
My main guess is that the load_plugins function in src/streamlink/session.py which looks over the plugins using pkgutil simply doesn't see the plugins as they're not included in the executable.

I do not know if the issue comes from the code of the project or a lack of pyinstaller configuration on my end. If there's some additional pyinstaller configuration I need to make streamlink compatible with pyinstaller, please let me know (and preferably add the information into the docs for others to know)

Expected / Actual behavior

Expected: The code runs without issue and the list of streams is retreived on both cases.
Actual behaviour: The code throws a NoPluginError on attempting to get the streams of any URL in the case of the executable created with pyinstaller.

Reproduction steps / Explicit stream URLs to test

Here is my test script main.py:

import streamlink

if __name__ == '__main__':
    try:
        print(list(streamlink.streams("https://www.youtube.com/watch?v=huxQs2PCUTU")))
    except streamlink.exceptions.NoPluginError:
        print("NoPluginError caught.")
    input()

running python main.py gives you a list of stream types.
running pyinstaller and then the resulting executable prints the message on catching the exception.

pyinstaller is called by:

pyinstaller --noconfirm --onefile --console  "main.py"
@back-to back-to added duplicate This issue or pull request already exists out of scope question labels Jan 23, 2021
@back-to
Copy link
Collaborator

back-to commented Jan 23, 2021

I do not know if the issue comes from the code of the project or a lack of pyinstaller configuration on my end.

depends on how you want to fix it.

you can make Streamlink compatible with pyinstaller or
you can make pyinstaller compatible with Streamlink

you can also search for some duplicates or maybe scripts to fix it

https://github.com/streamlink/streamlink/search?q=pyinstaller&type=issues
https://github.com/pyinstaller/pyinstaller/search?q=pkgutil&type=issues


If there's some additional pyinstaller configuration I need to make streamlink compatible with pyinstaller

we can't help you with this, since we don't use pyinstaller here


Ref #669

@RTFM90172155
Copy link

RTFM90172155 commented May 2, 2022

You can porting a project containing streamlink with PyInstaller in the following way:

  1. create spec file
pyi-makespec --onefile --console "main.py"
  1. edit spec file
    Open "main.spec" file and edit it as follows.
    My streamlink is version 2.4.0, but it also conflicts with the iso639 package, so I added it.
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_data_files, collect_submodules  # append

block_cipher = None

a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas = collect_data_files('streamlink.plugins', include_py_files=True) + collect_data_files('iso639'), # edit
    hiddenimports = collect_submodules('streamlink.plugins'),   # edit
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
  1. porting executable file
pyinstaller --noconfirm --clean "main.spec"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists out of scope question
Projects
None yet
Development

No branches or pull requests

3 participants