在Python 3.4中没有Python源文件运行

Mat*_*dge 21 python pyc python-3.x

我正在尝试运行Python应用程序而不保留.py源文件,只依赖于.pyc编译的文件.但是,当我删除.py源文件时,我收到导入错误.此功能在Python 2.7中有效,但在3.4中没有(使用新__pycache__结构).

这是一个示例目录结构:

package/
  __init__.py
  module.py
Run Code Online (Sandbox Code Playgroud)

Python 2.7

首先让我们看看当我使用Python 2.7时会发生什么(这是所需的行为)

$ python2 -c "from package import module"
$ find package -name "*.py" -delete
$ python2 -c "from package import module"
Run Code Online (Sandbox Code Playgroud)

这一切都很好,不会抛出任何错误.执行此操作后的目录结构如下所示,.pyc文件与原始.py文件一起:

package/
  __init__.pyc
  module.pyc
Run Code Online (Sandbox Code Playgroud)

Python 3.4

现在,让我们用Python 3.4做同样的事情,再次从我们的原始目录结构开始

$ python3 -c "from package import module"
$ find package -name "*.py" -delete
$ python3 -c "from package import module"
 Traceback (most recent call last):
   File "<string>", line 1, in <module>
 ImportError: cannot import name 'module'
Run Code Online (Sandbox Code Playgroud)

哦,它无法导入模块.有趣的是,我仍然可以python3 -c "import package"在这一点上安全地运行,但它无法从中获取任何模块.此时,目录结构与2.7中的目录结构略有不同,具体如下:

package/
  __pycache__/
      __init__.cpython-34.pyc
      module.cpython-34.pyc
Run Code Online (Sandbox Code Playgroud)

所以问题是这样的:为什么Python 3.4只能在给定.pyc文件的情况下正确导入/执行?这是否是理想的行为,这意味着必须在所有情况下保持来源?或者我错过了一些愚蠢的东西?

Bre*_*arn 28

根据PEP:

foo.py文件可能以某种方式被删除,同时将缓存的pyc文件保留在文件系统上.如果该__pycache__/foo.<magic>.pyc文件存在,但用于创建它的foo.py文件不存在,Python将在被要求导入foo时引发ImportError.换句话说,除非源文件存在,否则Python不会从缓存目录中导入pyc文件.

但:

但是为了继续支持无源分发,如果缺少源文件,Python将导入一个单独的pyc文件,如果它存在于源文件所在的位置.

因此,似乎__pycache__无源分发是互斥的.如果要删除源,则需要将.pyc文件移动到源所在的目录中.

  • 啊,就是这样!我昨天在数百万次迭代中尝试移动pyc文件,但问题是我没有从文件名中删除`<magic>`部分.所以对于未来的读者,你需要为每个pyc做以下几行:`mv package/__ pycache __/module.cpython-34.pyc package/module.pyc` (8认同)

Gnu*_*uth 24

没有足够的声誉来为BrenBarn的答案添加评论.所以这里有一些补充.

根据compileall doc:

__PRE__

因此,您可以运行python -m compileall -b .以递归方式编译此目录中的所有代码文件.