为什么 VLC .py 模块在 'media_player_new' 中返回 'NoneType'?

Why is VLC's .py modue returning 'NoneType' in 'media_player_new'?

几周来我一直在运行兜圈子,无法解决一个令人恼火的问题……首先;我正在 运行ning 64 位 Win10,64 位 Powershell 调用 python 3.9(也是 64 位),这是一个带有 Tk GUI 的应用程序,并使用 python-vlc。在笔记本电脑上 运行 数周以来一直很好,我现在正试图让它在具有相同设置(Win10、64 位 VLC、64 位 Python)的 PC 上运行。

错误可以在 Python shell:

中的几行简单的代码中重现
PS C:\Users\Vexen\OneDrive> python
Python 3.9.2 (tags/v3.9.2:1a79785, Feb 19 2021, 13:44:55) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import vlc
>>> p = vlc.MediaPlayer("C\:\Users\Vexen\OneDrive\test.mp3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Vexen\AppData\Local\Programs\Python\Python39\lib\site-packages\vlc.py", line 3327, in __new__
    o = instance.media_player_new()
AttributeError: 'NoneType' object has no attribute 'media_player_new'
>>>

或者,使用带有显式 .Instance() 的稍微不同的方法:

>>> import vlc
>>> i=vlc.Instance()
>>> p=i.MediaPlayer()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'MediaPlayer'

并测试我在它不起作用的机器上出现的结果:

>>> type(i)
<class 'NoneType'>

在笔记本电脑上显示 .

以下是我看过并尝试过的东西(下面每个都有更多详细信息):

  1. 实例化媒体播放器所需的正确代码
  2. 使用 vlc.Instance('--verbose 3')
  3. vlc.py 内置 GUI/demo 导致相同的错误
  4. 检查 VLC 是否可以打开 .mp3 文件
  5. 重新安装和 64 位检查
  6. VLC DLL 位置和 %PATH% 环境变量
  7. 正在检查vlc.py
  8. vlc.py 内部问题:Instance.new() 调用 _CFunctions returns None

(1) 创建播放器的代码

文档说如果没有手动创建实例,.MediaPlayer 会自动创建实例。这也在此处说明: 和 .

无论我采用哪种方式(直接在 Python 中,或通过将 frmMain.vlc 设置为 vlc.MediaPlayer() 在 gui 中保持打开状态,我都会得到相同的结果,所以我在这里只展示更简单的方法。

(2) i = vlc.Instance('--verbose 3')

Python VLC Script error: AttributeError: 'NoneType' object has no attribute 'media_player_new' 说使用 i = vlc.Instance('--verbose 3') 查看可能的错误消息:我的输出“C:\Windows\system32”并且没有错误。

在笔记本电脑上运行良好,它会输出一屏技术细节。

(3) vlc.py 内置 GUI/demo 导致相同的错误

查看 vlc.py 时,我发现它有一个内置的简单 GUI。当我 运行 它时,文件本身输出相同的错误:

PS C:\Users\Vexen\OneDrive> python C:\Users\Vexen\AppData\Local\Programs\Python\Python39\Lib\site-packages\vlc.py C:\Users\Vexen\OneDrive\test.mp3
AttributeError: 'NoneType' object has no attribute 'media_new' (C:\Users\Vexen\AppData\Local\Programs\Python\Python39\Lib\site-packages\vlc.py 3.0.11115 vs LibVLC b'3.0.12 Vetinari')

这让我认为这是 VLC 安装或后端 DLL 的固有特性。

(4) 检查 VLC 是否可以打开 .mp3 文件

以下使 VLC 完整应用程序打开并正确播放文件:

PS C:\Users\Vexen\OneDrive> C:\Users\Vexen\OneDrive\test.mp3

此外,故意为 .MediaPlayer() 提供错误的文件路径会产生相同的错误,因此,它会在解析文件路径参数之前遇到 None类型错误。

(5) 重新安装和 64 位检查

许多类似的问题都集中在 32 位和 64 位安装之间的不匹配上。例如。 PyInstaller with Python-VLC: No Attribute "media_player_new" Error and https://superuser.com/questions/1281731/how-to-install-64-bit-vlc-library-for-64-bit-python-3-on-windows。我已经卸载了 VLC 和 Python、重新启动、重新安装、重新启动并仔细检查我已经安装了所有的 64 位版本。

我从两台机器上卸载了它,并使用高级安装选项,使用完全相同的设置在两台机器上完成了自定义安装(不包括 Python 文档,包括 Tcl,包括 Python 启动器,为所有用户安装)。

检查 Python 在两台机器上都是 64 位的:

>>> import platform
>>> platform.architecture()[0]
'64bit'

获取新的 vlc.py 文件:

pip3 install python-vlc --force-reinstall

正在检查 vlc 版本,两台机器上的详细信息完全匹配:

PS C:\Users\Vexen\OneDrive> python -m vlc -v
vlc.py: 3.0.11115 (Sat Jul 25 15:07:40 2020 3.0.11)
LibVLC version: 3.0.12 Vetinari (0x3000c00)
LibVLC compiler: gcc version 6.4.0 (GCC)
Plugin path: C:\WINDOWS\system32
Python: 3.9.2 (64bit) Windows 10

当 运行使用 VLC 完整应用程序时,'About' 屏幕在两台机器上也显示“3.0.12 Vetinari”。

32 位和 64 位不匹配错误与我遇到的错误不同(未找到文件、%1 不兼容等),所以,这不是问题所在。

其他一般安装问题,例如 Python vlc install problems and ,涵盖了我已经做过的一些相同的事情。

(6) VLC DLL 位置和 %PATH% 环境变量

Python vlc install problems 和其他一些问题与 %PATH% 和 Python 不知道在哪里寻找 vlc DLL,但是,这不是我的问题。

Microsoft 表示 Sytem32 是 Windows 将搜索 DLL 的默认位置:https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order .

我已经遍历了 vlc.py,在“find_lib()”中,我可以看到它在 /system32/ 中选择了 libvlc.dll 的正确位置。我删除了 2x DLL 文件(另一个是 libvlccore.dll)并用较新安装的 VLC 中的较新副本替换它们。没什么区别,但是,这意味着我不需要担心 %PATH% 环境变量,因为它可以轻松自动地在 /system32/ 中找到 DLL。

此外,上面 python -m vlc -v 列出的 dll 版本正确地在 /system32/ 中找到它。

(7) 正在检查 vlc.py

我已经将文件从笔记本电脑(Python 可以调用 VLC 并正常播放 .mp3 文件)复制到桌面(导致错误),但结果相同。文件版本看起来完全一样。

验证我确切知道正在使用哪个 vly.py 已被使用;它在错误的 Stacktrace 中,并且:

>>> vlc.__file__

returns 两台机器上的预期文件路径。将它复制到本地目录不会改变任何内容(除了发生在新位置的文件中,如您所料)。

我还从 https://git.videolan.org/?p=vlc/bindings/python.git;a=blob;f=generated/3.0/vlc.py;h=fdb603002425e082b1d6b8ac08ab8322248d3ac7;hb=HEAD 下载了最新版本的 vlc.py。

此文件在同一行代码上产生相同的错误(尽管有几行号不同):

  File "C:\Users\Vexen\OneDrive\Music\Pyggy\vlc.py", line 3200, in __new__
    o = instance.media_player_new()
AttributeError: 'NoneType' object has no attribute 'media_player_new'

(8) vlc.py 内部问题:Instance.new() 调用 _CFunctions returns None

It 运行s find_lib() 正确地将 dll 位置设置为 system32。 Instance class 由 Instance.new() 初始化(我猜),它调用 libvlc_new() which returns [b'vlc' ],这看起来不错(不是 None)。但它随后将其传递给 _Cfunctions(通过 f()),后者 returns None。这作为 Instance() 实例返回,是问题的根源。

我在 vlc.py 中添加了一些 print() 语句(测试时,我倾向于将“Line xxxx”放在 print 语句中,以帮助我稍后删除 prints() !):

在PC上无法运行的地方:

Line 4685, lib_vlc_new() is sending the following to f(): 1 [b'vlc']
Line 4688 will return the results of f(argc, argv): None
Line 1883, Instance.__new__() is returning the following: None

在可以正常工作的笔记本电脑上:

Line 4685, lib_vlc_new() is sending the following to f():  1 [b'vlc']
Line 4688 will return the results of f(argc, argv):  <vlc.Instance object at 0x000001DCD37BA370>
Line 1883, Instance.__new__() is returning the following:  <vlc.Instance object at 0x000001DCD37BA400>

f是调用_Cfunctions的子函数。

在与这里的开发者社区交谈时,问题自行解决了。 https://github.com/oaubert/python-vlc/issues/170

我们的结束评论包括我们的最佳猜测:某处 Windows 内部缓存。我从 system32 中删除了 DLL,准备再次重新安装。我测试了该程序,它从“C:\Program Files\VideoLAN\VLC\libvlc.dll”而不是 /system32/ 目录中获取了 DLL。我强烈怀疑在 Windows 某处,.dll 被诸如预加载进程或 Windows 的其他一些模糊位缓存。没有面向用户的方式来清除一些 Windows 内部缓存。缓存在某个时候变得无效(3 周似乎是任意的(相当长的)缓存期,但 Windows 是出了名的不透明)。之后,它真正从新安装中加载了新版本。也许在那之前,我所有的尝试都因预加载缓存而失败。这只是一个猜测。

正确答案:继续尝试,即使卸载了以前的版本,手动删除 libvlc.dll 和 libvclcore.dll ,继续重新启动,继续检查版本号。最终。它会开始工作。