Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with Pynput and Pyinstaller on Ubuntu 20.04LTS GUI

I have a python script that uses the Pynput module. When I run the python script from terminal on Ubuntu [20.04LTS GUI] it runs perfectly.

$ pyinstaller --onefile vTwo.py
cd ./dist
./vTwo

Error occurs when running ./script:

ImportError: this platform is not supported: No module named 'pynput.keyboard._xorg'

Try one of the following resolutions:

 * Please make sure that you have an X server running, and that the DISPLAY environment variable is set correctly
[5628] Failed to execute script vTwo

If someone could advise me on what may be going wrong. I have had a look at the Pynput requirements page where they mention that it requires X server to be running in the background which should not be an issue as I have a GUI installed.

Also is there anyway to use Pynput on a system without a gui?

like image 224
arthem Avatar asked Dec 30 '22 19:12

arthem


1 Answers

The Solution

The solution is easy. Just include this module as a hidden import in the PyInstaller program:

python -m PyInstaller your_program.py --onefile --hidden-import=pynput.keyboard._xorg

If you also use the mouse with pynput, then you'll get the same error with the module pynput.mouse._xorg. So do this:

python -m PyInstaller your_program.py --onefile --hidden-import=pynput.keyboard._xorg --hidden-import=pynput.mouse._xorg

Warning! You'll likely get a different module that it doesn't find, if you're packaging for Windows or Mac. This is what you get for Linux. If you want your program to be cross-platform, then you'll have to package the program, for example, for Windows and test it to see which module it doesn't find and include it as a hidden import.

For example, if you want your program to work on Linux and Windows, use this command:

python -m PyInstaller your_program.py --onefile --hidden-import=pynput.keyboard._xorg --hidden-import=pynput.mouse._xorg --hidden-import=pynput.keyboard._win32 --hidden-import=pynput.mouse._win32

If you have a lot of hidden modules, then you may edit the .spec file and add the modules to the hiddenimports list like so (on PyInstaller 4.1):

hiddenimports=['pynput.keyboard._xorg', 'pynput.mouse._xorg'],

Why The Error

When you see an ImportError in a Python program packaged by PyInstaller, there is a high chance that the problem is that PyInstaller couldn't detect that specific import and didn't include it in the binary, hence the import error.

In the error message it tells you which module it didn't find:

ImportError: this platform is not supported: No module named 'pynput.keyboard._xorg'

which is pynput.keyboard._xorg, because you're on Linux.

It couldn't find the module, because it was imported in a "non-traditional" way. Look at the source code for pynput/_util/__init__.py in the backend function:

def backend(package):
    backend_name = os.environ.get(
        'PYNPUT_BACKEND_{}'.format(package.rsplit('.')[-1].upper()),
        os.environ.get('PYNPUT_BACKEND', None))
    if backend_name:
        modules = [backend_name]
    elif sys.platform == 'darwin':
        modules = ['darwin']
    elif sys.platform == 'win32':
        modules = ['win32']
    else:
        modules = ['xorg']

    errors = []
    resolutions = []
    for module in modules:
        try:
            return importlib.import_module('._' + module, package)
        except ImportError as e:
            errors.append(e)
            if module in RESOLUTIONS:
                resolutions.append(RESOLUTIONS[module])

    raise ImportError('this platform is not supported: {}'.format(
        '; '.join(str(e) for e in errors)) + ('\n\n'
            'Try one of the following resolutions:\n\n'
            + '\n\n'.join(
                ' * {}'.format(s)
                for s in resolutions))
            if resolutions else '')

You can see that it uses the import_module function from the importlib module to import the correct module for the platform. This is why it couldn't find the pynput.keyboard._xorg module.

Your Second Question

Also is there anyway to use Pynput on a system without a gui?

I don't know.

like image 198
Simon Teodor Mărăcine Avatar answered Jan 14 '23 02:01

Simon Teodor Mărăcine