Ubuntu 20.04LTS GUI 上 Pynput 和 Pyinstaller 的问题

Abd*_*mat 4 python python-3.x pynput

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

$ pyinstaller --onefile vTwo.py
cd ./dist
./vTwo
Run Code Online (Sandbox Code Playgroud)

运行 ./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
Run Code Online (Sandbox Code Playgroud)

如果有人可以就可能出现的问题向我提出建议。我看过 Pynput 要求页面,他们提到它需要 X 服务器在后台运行,这应该不是问题,因为我安装了 GUI。

还有无论如何在没有gui的系统上使用Pynput吗?

Sim*_*ine 9

解决方案

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

python -m PyInstaller your_program.py --onefile --hidden-import=pynput.keyboard._xorg
Run Code Online (Sandbox Code Playgroud)

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

python -m PyInstaller your_program.py --onefile --hidden-import=pynput.keyboard._xorg --hidden-import=pynput.mouse._xorg
Run Code Online (Sandbox Code Playgroud)

警告!如果您为 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
Run Code Online (Sandbox Code Playgroud)

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

hiddenimports=['pynput.keyboard._xorg', 'pynput.mouse._xorg'],
Run Code Online (Sandbox Code Playgroud)

为什么会出错

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

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

ImportError: this platform is not supported: No module named 'pynput.keyboard._xorg'
Run Code Online (Sandbox Code Playgroud)

也就是说pynput.keyboard._xorg,因为您使用的是 Linux。

它找不到该模块,因为它是以“非传统”方式导入的。看看源代码pynput/_util/__init__.pybackend功能:

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 '')
Run Code Online (Sandbox Code Playgroud)

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

你的第二个问题

还有无论如何在没有gui的系统上使用Pynput吗?

我不知道。