Python Rules

py_binary

py_binary(name, deps, srcs, data, args, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, features, imports, legacy_create_init, licenses, main, output_licenses, python_version, restricted_to, srcs_version, stamp, tags, testonly, toolchains, visibility)

A py_binary is an executable Python program consisting of a collection of .py source files (possibly belonging to other py_library rules), a *.runfiles directory tree containing all the code and data needed by the program at run-time, and a stub script that starts up the program with the correct initial environment and data.

Examples

py_binary(
    name = "foo",
    srcs = ["foo.py"],
    data = [":transform"],  # a cc_binary which we invoke at run time
    deps = [
        "//pyglib",
        ":foolib",  # a py_library
    ],
)

If you want to run a py_binary from within another binary or test (for example, running a python binary to set up some mock resource from within a java_test) then the correct approach is to make the other binary or test depend on the py_binary in its data section. The other binary can then locate the py_binary relative to the source directory.

py_binary(
    name = "test_main",
    srcs = ["test_main.py"],
    deps = [":testlib"],
)

java_library(
    name = "testing",
    srcs = glob(["*.java"]),
    data = [":test_main"]
)

Arguments

Attributes
name

Name; required

A unique name for this target.


If main is unspecified, this should be the same as the name of the source file that is the main entry point of the application, minus the extension. For example, if your entry point is called main.py, then your name should be main.
deps

List of labels; optional

The list of other libraries to be linked in to the binary target. See general comments about deps at Attributes common to all build rules. These are generally py_library rules.
srcs

List of labels; required

The list of source (.py) files that are processed to create the target. This includes all your checked-in code and any generated source files. Library targets belong in deps instead, while other binary files needed at runtime belong in data.
imports

List of strings; optional

List of import directories to be added to the PYTHONPATH.

Subject to "Make variable" substitution. These import directories will be added for this rule and all rules that depend on it (note: not the rules this rule depends on. Each directory will be added to PYTHONPATH by py_binary rules that depend on this rule.

Absolute paths (paths that start with /) and paths that references a path above the execution root are not allowed and will result in an error.

legacy_create_init

Integer; optional; default is -1

Whether to implicitly create empty __init__.py files in the runfiles tree. These are created in every directory containing Python source code or shared libraries, and every parent directory of those directories, excluding the repo root directory. The default, auto, means true unless --incompatible_default_to_explicit_init_py is used. If false, the user is responsible for creating (possibly empty) __init__.py files and adding them to the srcs of Python targets as required.
main

Label; optional

The name of the source file that is the main entry point of the application. This file must also be listed in srcs. If left unspecified, name is used instead (see above). If name does not match any filename in srcs, main must be specified.
python_version

String; optional; nonconfigurable; default is "_INTERNAL_SENTINEL"

Whether to build this target (and its transitive deps) for Python 2 or Python 3. Valid values are "PY2" and "PY3" (the default).

The Python version is always reset (possibly by default) to whatever version is specified by this attribute, regardless of the version specified on the command line or by other higher targets that depend on this one.

If you want to select() on the current Python version, you can inspect the value of @rules_python//python:python_version. See here for more information.

Bug warning: This attribute sets the version for which Bazel builds your target, but due to #4815, the resulting stub script may still invoke the wrong interpreter version at runtime. See this workaround, which involves defining a py_runtime target that points to either Python version as needed, and activating this py_runtime by setting --python_top.

srcs_version

String; optional; default is "PY2AND3"

This attribute declares the target's srcs to be compatible with either Python 2, Python 3, or both. To actually set the Python runtime version, use the python_version attribute of an executable Python rule (py_binary or py_test).

Allowed values are: "PY2AND3", "PY2", and "PY3". The values "PY2ONLY" and "PY3ONLY" are also allowed for historic reasons, but they are essentially the same as "PY2" and "PY3" and should be avoided.

Note that only the executable rules ({@code py_binary} and {@code py_library}) actually verify the current Python version against the value of this attribute. (This is a feature; since {@code py_library} does not change the current Python version, if it did the validation, it'd be impossible to build both {@code PY2ONLY} and {@code PY3ONLY} libraries in the same invocation.) Furthermore, if there is a version mismatch, the error is only reported in the execution phase. In particular, the error will not appear in a {@code bazel build --nobuild} invocation.)

To get diagnostic information about which dependencies introduce version requirements, you can run the find_requirements aspect on your target:

          bazel build <your target> \
              --aspects=@rules_python//python:defs.bzl%find_requirements \
              --output_groups=pyversioninfo
          
This will build a file with the suffix -pyversioninfo.txt giving information about why your target requires one Python version or another. Note that it works even if the given target failed to build due to a version conflict.
stamp

Integer; optional; default is -1

Enable link stamping. Whether to encode build information into the binary. Possible values:
  • stamp = 1: Stamp the build information into the binary. Stamped binaries are only rebuilt when their dependencies change. Use this if there are tests that depend on the build information.
  • stamp = 0: Always replace build information by constant values. This gives good build result caching.
  • stamp = -1: Embedding of build information is controlled by the --[no]stamp Bazel flag.

py_library

py_library(name, deps, srcs, data, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, features, imports, licenses, restricted_to, srcs_version, tags, testonly, visibility)

Arguments

Attributes
name

Name; required

A unique name for this target.

deps

List of labels; optional

The list of other libraries to be linked in to the binary target. See general comments about deps at Attributes common to all build rules. These are generally py_library rules.
srcs

List of labels; optional

The list of source (.py) files that are processed to create the target. This includes all your checked-in code and any generated source files.
imports

List of strings; optional

List of import directories to be added to the PYTHONPATH.

Subject to "Make variable" substitution. These import directories will be added for this rule and all rules that depend on it (note: not the rules this rule depends on. Each directory will be added to PYTHONPATH by py_binary rules that depend on this rule.

Absolute paths (paths that start with /) and paths that references a path above the execution root are not allowed and will result in an error.

srcs_version

String; optional; default is "PY2AND3"

This attribute declares the target's srcs to be compatible with either Python 2, Python 3, or both. To actually set the Python runtime version, use the python_version attribute of an executable Python rule (py_binary or py_test).

Allowed values are: "PY2AND3", "PY2", and "PY3". The values "PY2ONLY" and "PY3ONLY" are also allowed for historic reasons, but they are essentially the same as "PY2" and "PY3" and should be avoided.

Note that only the executable rules ({@code py_binary} and {@code py_library}) actually verify the current Python version against the value of this attribute. (This is a feature; since {@code py_library} does not change the current Python version, if it did the validation, it'd be impossible to build both {@code PY2ONLY} and {@code PY3ONLY} libraries in the same invocation.) Furthermore, if there is a version mismatch, the error is only reported in the execution phase. In particular, the error will not appear in a {@code bazel build --nobuild} invocation.)

To get diagnostic information about which dependencies introduce version requirements, you can run the find_requirements aspect on your target:

          bazel build <your target> \
              --aspects=@rules_python//python:defs.bzl%find_requirements \
              --output_groups=pyversioninfo
          
This will build a file with the suffix -pyversioninfo.txt giving information about why your target requires one Python version or another. Note that it works even if the given target failed to build due to a version conflict.

py_test

py_test(name, deps, srcs, data, args, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, features, flaky, imports, legacy_create_init, licenses, local, main, python_version, restricted_to, shard_count, size, srcs_version, stamp, tags, testonly, timeout, toolchains, visibility)

A py_test() rule compiles a test. A test is a binary wrapper around some test code.

Examples

py_test(
    name = "runtest_test",
    srcs = ["runtest_test.py"],
    deps = [
        "//path/to/a/py/library",
    ],
)

It's also possible to specify a main module:

py_test(
    name = "runtest_test",
    srcs = [
        "runtest_main.py",
        "runtest_lib.py",
    ],
    main = "runtest_main.py",
)

Arguments

Attributes
name

Name; required

A unique name for this target.

deps

List of labels; optional

The list of other libraries to be linked in to the binary target. See general comments about deps at Attributes common to all build rules. These are generally py_library rules.
srcs

List of labels; required

The list of source (.py) files that are processed to create the target. This includes all your checked-in code and any generated source files. Library targets belong in deps instead, while other binary files needed at runtime belong in data.
imports

List of strings; optional

List of import directories to be added to the PYTHONPATH.

Subject to "Make variable" substitution. These import directories will be added for this rule and all rules that depend on it (note: not the rules this rule depends on. Each directory will be added to PYTHONPATH by py_binary rules that depend on this rule.

Absolute paths (paths that start with /) and paths that references a path above the execution root are not allowed and will result in an error.

legacy_create_init

Integer; optional; default is -1

Whether to implicitly create empty __init__.py files in the runfiles tree. These are created in every directory containing Python source code or shared libraries, and every parent directory of those directories, excluding the repo root directory. The default, auto, means true unless --incompatible_default_to_explicit_init_py is used. If false, the user is responsible for creating (possibly empty) __init__.py files and adding them to the srcs of Python targets as required.
main

Label; optional

The name of the source file that is the main entry point of the application. This file must also be listed in srcs. If left unspecified, name is used instead (see above). If name does not match any filename in srcs, main must be specified.
python_version

String; optional; nonconfigurable; default is "_INTERNAL_SENTINEL"

Whether to build this target (and its transitive deps) for Python 2 or Python 3. Valid values are "PY2" and "PY3" (the default).

The Python version is always reset (possibly by default) to whatever version is specified by this attribute, regardless of the version specified on the command line or by other higher targets that depend on this one.

If you want to select() on the current Python version, you can inspect the value of @rules_python//python:python_version. See here for more information.

Bug warning: This attribute sets the version for which Bazel builds your target, but due to #4815, the resulting stub script may still invoke the wrong interpreter version at runtime. See this workaround, which involves defining a py_runtime target that points to either Python version as needed, and activating this py_runtime by setting --python_top.

srcs_version

String; optional; default is "PY2AND3"

This attribute declares the target's srcs to be compatible with either Python 2, Python 3, or both. To actually set the Python runtime version, use the python_version attribute of an executable Python rule (py_binary or py_test).

Allowed values are: "PY2AND3", "PY2", and "PY3". The values "PY2ONLY" and "PY3ONLY" are also allowed for historic reasons, but they are essentially the same as "PY2" and "PY3" and should be avoided.

Note that only the executable rules ({@code py_binary} and {@code py_library}) actually verify the current Python version against the value of this attribute. (This is a feature; since {@code py_library} does not change the current Python version, if it did the validation, it'd be impossible to build both {@code PY2ONLY} and {@code PY3ONLY} libraries in the same invocation.) Furthermore, if there is a version mismatch, the error is only reported in the execution phase. In particular, the error will not appear in a {@code bazel build --nobuild} invocation.)

To get diagnostic information about which dependencies introduce version requirements, you can run the find_requirements aspect on your target:

          bazel build <your target> \
              --aspects=@rules_python//python:defs.bzl%find_requirements \
              --output_groups=pyversioninfo
          
This will build a file with the suffix -pyversioninfo.txt giving information about why your target requires one Python version or another. Note that it works even if the given target failed to build due to a version conflict.
stamp

Integer; optional; default is 0

See the section on py_binary() arguments, except that the stamp argument is set to 0 by default for tests.