linux 上 Python3.6 的回溯中的 ModuleNotFoundError

ModuleNotFoundError in tracebacks with Python3.6 on linux

installed Python 3.6 on Ubuntu 16.04 by using Jonathon Fernyhough's PPA:

sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6

我使用新的文字字符串插值创建了一个字符串,但我提供了一个无效的格式说明符。我不仅得到了预期的ValueError: Invalid format specifier,还得到了意想不到的ModuleNotFoundError: No module named 'apt_pkg'.

$ python3.6
Python 3.6.0 (default, Dec 29 2016, 21:40:36) 
[GCC 5.4.1 20161202] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> value = 4 * 20
>>> f'the value is {value:%A}'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 23, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

Original exception was:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier

我向 Python bug tracker 报告了此事。其中指出:

It seems to be vendor's issue not CPython itself. This same issue also happens in Ubuntu 16.10's Python 3.6. Raise any exception can cause this:

Python 3.6.0b2 (default, Oct 11 2016, 05:27:10) 
[GCC 6.2.0 20161005] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> raise Exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 23, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

Original exception was:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception
>>> 

Also see https://bugs.launchpad.net/ubuntu/+source/python3.6/+bug/1631367.

最后,这个问题被评论关闭了

Yes, this appears to be the vendor's failure reporting infrastructure that is failing. Why they'd want a report for every traceback at the interactive prompt is beyond me, but that appears to be what they are trying to do.

我现在的问题是:

  1. 我该如何解读这条评论?在这种情况下,供应商是 Jonathon Fernyhough 的 PPA 吗?他是否对他分发的 Python 代码进行了更改,以便它尝试为每个产生回溯的异常提交报告?
  2. 我需要通知谁或者我需要在哪里提交错误来解决这个问题?

在我将这个问题发布到 Whosebug 之后,Barry A. Warsaw 在问题跟踪器

中做了以下 comment

Please understand that installing Python 3.6 from a random PPA does not provide full support for this version of the interpreter. Python 3.6 is not yet a supported version in any version of Ubuntu (which I'm assuming your using), although we are working on it for 17.04.

Very often, you can install a new Python 3 interpreter package and many things will work because the Ubuntu infrastructure shares pure-Python modules across all installed Python 3's. Technically speaking, they will all have /usr/lib/python3/dist-packages on their sys.path so any third party pure-Python module built for a support version of Python 3 will be importable by any (package-built) installed version of Python 3.

But that 1) is a long way from saying that those third-party modules will work; 2) does not include any packages containing C extension modules, which must be rebuilt for the specific interpreter version.

Supporting a new version of Python is a long process, for which we are just starting. Please engage with ubuntu-devel@ubuntu.com for details.

Ubuntu does install a standard exception handler so that when Python applications and such crash, we can gather crash statistics, so that we can devote resources to fixing common problems and regressions. apport (which you see in the traceback) is that crash reporting infrastructure. apport calls apt_pkg, which is an (C++) extension module and thus won't have been built for the version of Python 3.6 you installed from that PPA, unless of course the PPA owner (who I don't know) has also done an archive-wide Python 3 rebuild. Since I'm in the process of setting that up, and I know it's quite a bit of work, I doubt that's been done for this rather random PPA.

The ubuntu-devel mailing list is a better place to discuss the ongoing work to bring Python 3.6 as a supported version on Ubuntu.

我通过首先为 Python 3 安装 python-apt 软件包解决了 Python 3.6 的这个问题:

sudo apt install python3-apt

之后,我换到dist-packages目录,将apt_pkg[...].so文件复制到新的默认文件名apt_pkg.so,也被Python3.6识别:

cd /usr/lib/python3/dist-packages
sudo cp apt_pkg.cpython-34m-i386-linux-gnu.so apt_pkg.so

现在所有 ModuleNotFoundError: No module named 'apt_pkg' 异常都在预期抛出的错误消息中消失。

如果投票最多的答案不适合您,请尝试以下步骤(请记住,您必须更改 [版本]):

  1. 运行 这个命令 sudo apt install python3-apt
  2. 进入目录cd /usr/lib/python3/dist-packages
  3. 运行 ls 找到正确版本的 apt_pkg.cpython-[version]-i386-linux-gnu.so 在我的例子中是 35m
  4. 创建符号链接sudo cp apt_pkg.cpython-[version]-i386-linux-gnu.so apt_pkg.so不要忘记:输入您的[版本]

疑难解答

如果出现错误 cp: cannot stat 'apt_pkg.cpython-[your-version]-i386-linux-gnu.so': No such file or directory 请尝试以下命令:

  1. rm -rf apt_pkg.so
  2. 创建符号链接sudo cp apt_pkg.cpython-[version]-i386-linux-gnu.so apt_pkg.so不要忘记:输入您的[版本]

我删除了 python3-apt,这似乎已经解决了 Python 3.8

sudo apt-get remove --purge python3-apt
sudo apt-get install python3-apt