17.12. compileall — 将源码编译为字节码

未匹配的标注

目的:将源代码文件转换为字节编译的版本。

这个 compileall 模块可以将 Python 源代码文件找出来并将他们编译为字节码,之后将结果保存成 .pyc 文件。

编译一个文件夹

这个 compile_dir() 方法用于递归式地扫描一个文件夹并对其中的文件进行字节编译。

compileall_compile_dir.py

import compileall
import glob

def show(title):
    print(title)
    for filename in glob.glob('examples/**',
                              recursive=True):
        print('  {}'.format(filename))
    print()

show('Before')

compileall.compile_dir('examples')

show('\nAfter')

默认情况下,所有的子文件夹的扫描深度都是 10。输出文件被写入到一个叫做 __pycache__ 的文件夹并基于 Python 编译器的版本来命名。

$ python3 compileall_compile_dir.py

Before
  examples/
  examples/README
  examples/a.py
  examples/subdir
  examples/subdir/b.py

Listing 'examples'...
Compiling 'examples/a.py'...
Listing 'examples/subdir'...
Compiling 'examples/subdir/b.py'...

After
  examples/
  examples/README
  examples/a.py
  examples/subdir
  examples/subdir/__pycache__
  examples/subdir/__pycache__/b.cpython-36.pyc
  examples/subdir/b.py
  examples/__pycache__
  examples/__pycache__/a.cpython-36.pyc

忽略不参与编译的文件

若要过滤文件夹,可以使用 rx 参数来提供一个正则表达式用于匹配你想要排除的文件夹的名称。

compileall_exclude_dirs.py

import compileall
import re

compileall.compile_dir(
    'examples',
    rx=re.compile(r'/subdir'),
)

该版代码可以将名为 subdir 的子文件夹中的文件排除掉。

$ python3 compileall_exclude_dirs.py

Listing 'examples'...
Compiling 'examples/a.py'...
Listing 'examples/subdir'...

其中, maxlevels 参数用于控制递归的深度。比如,想完全避免递归,可以给该参数传入 0

compileall_recursion_depth.py

import compileall
import re

compileall.compile_dir(
    'examples',
    maxlevels=0,
)

只有传给了 compile_dir() 方法的文件夹中的文件才会被编译。

$ python3 compileall_recursion_depth.py

Listing 'examples'...
Compiling 'examples/a.py'...

编译 sys.path

所有在 sys.path 路径下找到的 Python 源代码文件都可以通过对 compile_path() 方法的一次简单调用来进行编译。

compileall_path.py

import compileall
import sys

sys.path[:] = ['examples', 'notthere']
print('sys.path =', sys.path)
compileall.compile_path()

这个例子将 sys.path 的默认内容替换掉用于避免运行脚本时的许可错误,但仍然可以展现出该方法的默认行为。注意, maxlevels 的值默认设为了 0

$ python3 compileall_path.py

sys.path = ['examples', 'notthere']
Listing 'examples'...
Compiling 'examples/a.py'...
Listing 'notthere'...
Can't list 'notthere'

编译独立文件

若要编译单个文件,而不是一整个文件夹的文件,可使用 compile_file() 方法。

compileall_compile_file.py

import compileall
import glob

def show(title):
    print(title)
    for filename in glob.glob('examples/**',
                              recursive=True):
        print('  {}'.format(filename))
    print()

show('Before')

compileall.compile_file('examples/a.py')

show('\nAfter')

第一个参数可以是文件名,完整路径或相对路径。

$ python3 compileall_compile_file.py

Before
  examples/
  examples/README
  examples/a.py
  examples/subdir
  examples/subdir/b.py

Compiling 'examples/a.py'...

After
  examples/
  examples/README
  examples/a.py
  examples/subdir
  examples/subdir/b.py
  examples/__pycache__
  examples/__pycache__/a.cpython-36.pyc

在命令行中执行编译

在命令行中调用 compileall 也是可以的,所以这个模块可以通过 Makefile 来集成到构建系统中。比如:

$ python3 -m compileall -h

usage: compileall.py [-h] [-l] [-r RECURSION] [-f] [-q] [-b] [-d
DESTDIR]
                     [-x REGEXP] [-i FILE] [-j WORKERS]
                     [FILE|DIR [FILE|DIR ...]]

Utilities to support installing Python libraries.

positional arguments:
  FILE|DIR              zero or more file and directory names to
compile; if
                        no arguments given, defaults to the
equivalent of -l
                        sys.path

optional arguments:
  -h, --help            show this help message and exit
  -l                    don't recurse into subdirectories
  -r RECURSION          control the maximum recursion level. if
`-l` and `-r`
                        options are specified, then `-r` takes
precedence.
  -f                    force rebuild even if timestamps are up
to date
  -q                    output only error messages; -qq will
suppress the
                        error messages as well.
  -b                    use legacy (pre-PEP3147) compiled file
locations
  -d DESTDIR            directory to prepend to file paths for
use in compile-
                        time tracebacks and in runtime
tracebacks in cases
                        where the source file is unavailable
  -x REGEXP             skip files matching the regular
expression; the regexp
                        is searched for in the full path of each
file
                        considered for compilation
  -i FILE               add all the files and directories listed
in FILE to
                        the list considered for compilation; if
"-", names are
                        read from stdin
  -j WORKERS, --workers WORKERS
                        Run compileall concurrently

重新创建下先前的例子,忽略掉 subdir 文件夹,运行:

$ python3 -m compileall -x '/subdir' examples

Listing 'examples'...
Compiling 'examples/a.py'...
Listing 'examples/subdir'...

供参考

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/pymotw/compilea...

译文地址:https://learnku.com/docs/pymotw/compilea...

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~