关于python:如何避免.pyc文件?

How to avoid .pyc files?

我可以在不生成编译的.pyc文件的情况下运行python解释器吗?


从"Python 2.6中的新功能 - 解释器更改":

Python can now be prevented from
writing .pyc or .pyo files by
supplying the -B switch to the Python
interpreter, or by setting the
PYTHONDONTWRITEBYTECODE environment
variable before running the
interpreter. This setting is available
to Python programs as the
sys.dont_write_bytecode variable, and
Python code can change the value to
modify the interpreter’s behaviour.

更新2010-11-27:Python 3.2通过引入特殊的__pycache__子文件夹解决了使用.pyc文件混乱源文件夹的问题,请参阅Python 3.2中的新增功能 - PYC存储库目录。


1
2
3
import sys

sys.dont_write_bytecode = True


实际上有一种方法可以在Python 2.3+中实现它,但它有点深奥。我不知道你是否意识到这一点,但你可以做到以下几点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ unzip -l /tmp/example.zip
 Archive:  /tmp/example.zip
   Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'

根据zipimport库:

Any files may be present in the ZIP archive, but only files .py and .py[co] are available for import. ZIP import of dynamic modules (.pyd, .so) is disallowed. Note that if an archive only contains .py files, Python will not attempt to modify the archive by adding the corresponding .pyc or .pyo file, meaning that if a ZIP archive doesn't contain .pyc files, importing may be rather slow.

因此,您所要做的就是压缩文件,将zipfile添加到sys.path然后导入它们。

如果你是为UNIX构建这个,你也可以考虑使用这个配方打包你的脚本:unix zip executable,但是请注意,如果你计划使用stdin或从sys.args读取任何内容,你可能需要调整它(它可以是完成没有太多麻烦)。

根据我的经验,性能不会因此而受到太大影响,但在以这种方式导入任何非常大的模块之前,您应该三思而后行。


在2.5中,除了不向用户提供对目录的写访问权之类的措施之外,没有办法压制它。

但是在python 2.6和3.0中,sys模块中可能有一个名为"dont_write_bytecode"的设置可以设置为抑制它。也可以通过传递"-B"选项或设置环境变量"PYTHONDONTWRITEBYTECODE"来设置


您可以在源中设置sys.dont_write_bytecode = True,但这必须在加载的第一个python文件中。如果执行python somefile.py,则不会获得somefile.pyc

使用setup.pyentry_points=安装实用程序时,将在启动脚本中设置sys.dont_write_bytecode。因此,您不能依赖setuptools生成的"默认"启动脚本。

如果您自己使用python文件作为参数启动Python,则可以指定-B

1
python -B somefile.py

无论如何都不会生成somefile.pyc,但也没有导入其他文件的.pyc文件。

如果你有一些实用程序myutil并且你无法改变它,它将不会将-B传递给python解释器。只需通过设置环境变量PYTHONDONTWRITEBYTECODE即可启动它:

1
PYTHONDONTWRITEBYTECODE=x myutil

我在测试套件中有几个测试用例,之前我在Mac终端中运行测试套件,如下所示:

1
python LoginSuite.py

以这种方式运行命令我的目录正在填充.pyc文件。我尝试了下面提到的方法,它解决了这个问题:

1
python -B LoginSuite.py

如果要将测试用例导入测试套件并在命令行上运行套件,则此方法有效。


对于运行Python解释器的用户,您可以将模块所在的目录设置为只读。

我不认为有更优雅的选择。 PEP 304似乎试图为此引入一个简单的选项,但它似乎已被放弃。

我想你可能还有其他一些问题需要解决,因为禁用.py [co]似乎是一种解决方法,但攻击这个原始问题可能更好。


从Python 3.8开始,您可以使用环境变量PYTHONPYCACHEPREFIX为Python定义缓存目录。

从Python文档:

If this is set, Python will write .pyc files in a mirror directory tree at this path, instead of in pycache directories within the source tree. This is equivalent to specifying the -X pycache_prefix=PATH option.

如果将以下行添加到Linux中的./profile

1
export PYTHONPYCACHEPREFIX="$HOME/.cache/cpython/"

Python不会在项目目录中创建恼人的__pycache__目录,而是将它们全部放在~/.cache/cpython/之下


ipython 6.2.1 using python 3.5.2的解决方案(在Ubuntu 16.04和Windows 10上测试):

如果在Ipython解释器中设置或在~/.ipython/profile-default/startup/00-startup.ipy启动期间Ipython,则Ipython不尊重%env PYTHONDONTWRITEBYTECODE =1
而是在~.ipython/profile-default/startup/00-startup.py中使用以下内容

1
2
import sys
Sys.dont_write_bytecode=True

据我所知,python将编译你"导入"的所有模块。但是python不会使用以下命令编译运行python脚本:"python script.py"(但它会编译脚本导入的任何模块)。

真正的问题是为什么你不想让python编译模块?如果他们挡路的话,你可以自动化一种清理它们的方法。