Ubuntu 20.04LTS GUI 上的 Pynput 和 Pyinstaller 问题

Problems with Pynput and Pyinstaller on Ubuntu 20.04LTS GUI

我有一个使用 Pynput 模块的 python 脚本。当我 运行 来自 Ubuntu [20.04LTS GUI] 终端的 python 脚本时,它 运行 非常完美。

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

运行ning ./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

如果有人可以告诉我可能出了什么问题。我查看了 Pynput 要求页面,他们提到它需要 X 服务器在后台 运行ning,这应该不是问题,因为我安装了 GUI。

还有没有 gui 的系统可以使用 Pynput 吗?

解决方案

解决方法很简单。只需将此模块作为隐藏导入包含在 PyInstaller 程序中:

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

如果您还使用带有 pynput 的鼠标,那么您将在模块 pynput.mouse._xorg 中遇到相同的错误。所以这样做:

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

警告!如果您为 Windows 或 Mac 打包,您可能会得到一个它找不到的不同模块。这就是 Linux 的结果。如果您希望您的程序是跨平台的,那么您必须打包程序,例如 Windows 并测试它以查看它找不到哪个模块并将其作为隐藏导入包含在内。

例如,如果您希望程序在 Linux 和 Windows 上运行,请使用此命令:

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

如果你有很多隐藏模块,那么你可以编辑 .spec 文件并将模块添加到 hiddenimports 列表中,就像这样(在 PyInstaller 4.1 上):

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

为什么会出错

当您在 PyInstaller 打包的 Python 程序中看到 ImportError 时,问题很可能是 PyInstaller 无法检测到该特定导入并且没有包含它在二进制文件中,因此出现导入错误。

在错误消息中,它告诉您找不到哪个模块:

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

这是 pynput.keyboard._xorg,因为你在 Linux。

找不到模块,因为它是以“非传统”方式导入的。看backend函数中pynput/_util/__init__.py的源码:

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 '')

您可以看到它使用 importlib 模块中的 import_module 函数为平台导入正确的模块。这就是为什么它找不到 pynput.keyboard._xorg 模块。

你的第二个问题

还有在没有图形用户界面的系统上使用 Pynput 吗?

我不知道。