ModuleNotFoundError: No module named 'plyer.platforms' when EXE created by pyinstaller runs plyer.filechooser.open_file() and choose_dir()

Viewed 1258

My python script with kivy GUI runs smoothly in Pycharm or Spyder IDE. After creating the EXE (Windows) using pyinstaller, the EXE can run with the GUI appearing without any issues. However when I click buttons that run plyer.filechooser.open_file() or plyer.filechooser.choose_dir(), this error appears:

 Traceback (most recent call last):
   File "plyer\utils.py", line 96, in _ensure_obj
 ModuleNotFoundError: No module named 'plyer.platforms'
[INFO   ] [Base        ] Leaving application in progress...

I just realized that the output directory created by pyinstaller under "dist" directory contains the used packages in my script such as pandas, numpy, pyexcelerate etc. but NOT plyer. That is strange because my script has explicitly import plyer at the beginning.

My spec file for pyinstaller is shown below. The reason I'm using plyer to select files is because of its small size whereas PyQt5 creates huge EXE size while kivy FileChooser does not show all hard drives available in a user's computer (if anyone knows solution for this would be great).

import os
from os.path import join

from kivy import kivy_data_dir
from kivy.deps import sdl2, glew
from kivy.tools.packaging import pyinstaller_hooks as hooks


block_cipher = None
kivy_deps_all = hooks.get_deps_all()
kivy_factory_modules = hooks.get_factory_modules()

# list of data filepath (your *.kv, image files, kivymd files) to copy to the output directory
datas = [('./gui.kv', '.'),
         ('./venv/Lib/site-packages/kivymd', 'kivymd')
        ]

# list of modules to exclude from Analysis
excludes_a = ['Tkinter', '_tkinter', 'twisted', 'docutils', 'pygments']

# list of hiddenimports
hiddenimports = kivy_deps_all['hiddenimports'] + kivy_factory_modules

# binary data
sdl2_bin_tocs = [Tree(p) for p in sdl2.dep_bins]
glew_bin_tocs = [Tree(p) for p in glew.dep_bins]
bin_tocs = sdl2_bin_tocs + glew_bin_tocs

# assets
kivy_assets_toc = Tree(kivy_data_dir, prefix=join('kivy_install', 'data'))
# source_assets_toc = Tree("images", prefix="images")
# assets_toc = [kivy_assets_toc, source_assets_toc]
assets_toc = [kivy_assets_toc]

tocs = bin_tocs + assets_toc


a = Analysis(['main.py'],
             pathex=[os.getcwd()],
             binaries=None,
             datas=datas,
             hiddenimports=hiddenimports,
             hookspath=[],
             runtime_hooks=[],
             excludes=excludes_a,
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)


pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe1 = EXE(pyz,
           a.scripts,
           name='main',   # name of output *.exe file
           exclude_binaries=True,
           # icon=join('images', 'mywinapp.ico'),
           debug=False,
           strip=False,
           upx=True,
           console=True)  # set to console-based, NOT window-based.

coll = COLLECT(exe1,
               a.binaries,
               a.zipfiles,
               a.datas,
               *tocs,
               strip=False,
               upx=True,
               name='Parser')
3 Answers

I also had the same issue.

My fix was to add the following argument while creating the exe with pyinstaller

--hidden-import plyer.platforms.win.notification

add following hidden import to spec file

a = Analysis(
   ...
   hiddenimports=['plyer.platforms.win.filechooser'],
   ...

The problem is caused by missing hidden imports. Try to include "platform-specific module" like brsaylor did in Windows notification - NotImplementedError: No usable implementation found! #485:

https://github.com/kivy/plyer/issues/485#issuecomment-457880444

I was having a similar issue with the FileChooser on macos, and I solved it by adding the platform-specific module to hiddenimports in the spec file. For this issue, the change would be something like:

a = Analysis(
   ...
   hiddenimports=['plyer.platforms.win.notification'],
   ...
Related