【问题标题】:Can't use Python's sh module in Bazel genrule无法在 Bazel genrule 中使用 Python 的 sh 模块
【发布时间】:2023-03-31 13:59:01
【问题描述】:

当我从 bazel genrule 运行一个使用“sh”模块的 python 脚本时,它失败了:

INFO: Analysed target //src:foo_gen (8 packages loaded).
INFO: Found 1 target...
ERROR: /home/libin11/workspace/test/test/src/BUILD:1:1: Executing genrule //src:foo_gen failed (Exit 1)
Traceback (most recent call last):
  File "src/test.py", line 2, in <module>
    sh.touch("foo.bar")
  File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1427, in __call__
    return RunningCommand(cmd, call_args, stdin, stdout, stderr)
  File "/usr/local/lib/python2.7/dist-packages/sh.py", line 767, in __init__
    self.call_args, pipe, process_assign_lock)
  File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1784, in __init__
    self._stdout_read_fd, self._stdout_write_fd = pty.openpty()
  File "/usr/lib/python2.7/pty.py", line 29, in openpty
    master_fd, slave_name = _open_terminal()
  File "/usr/lib/python2.7/pty.py", line 70, in _open_terminal
    raise os.error, 'out of pty devices'
OSError: out of pty devices
Target //src:foo_gen failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 2.143s, Critical Path: 0.12s
INFO: 0 processes.
FAILED: Build did NOT complete successfully

我想将第三方项目集成到我自己的项目中。第三方项目是用python脚本构建的,所以我想用bazel genrule构建项目。

这是一个示例文件列表:

.
├── src
│   ├── BUILD
│   └── test.py
└── WORKSPACE

WORKSPACE 为空,BUILD 为:

genrule(
    name = "foo_gen",
    srcs = glob(["**/*"]),
    outs = ["foo.bar"],
    cmd = "python $(location test.py)",
)

test.py 是:

import sh
sh.touch("foo.bar")

然后运行:

bazel build //src:foo_gen

操作系统:Ubuntu 16.04 bazel:发布 0.14.1

【问题讨论】:

    标签: python bazel


    【解决方案1】:

    看起来如果您将调用更改为 sh.touch("foo.bar", _tty_in=False, _tty_out=False) 它可以工作,但您仍然需要对 genrule 进行一些修改,否则它不会产生输出。

    我更喜欢使用 bazel python rules 导入 pip 依赖项,因此我可以为我的 genrule 创建工具。这样,bazel 会处理 pip 要求安装,而您不必对 test.py 文件进行 chmod。

    load("@my_deps//:requirements.bzl", "requirement")
    
    py_binary(
        name = "foo_tool",
        srcs = [
            "test.py",
        ],
        main = "test.py",
        deps = [
            requirement("sh"),
        ],
    )
    
    genrule(
        name = "foo_gen",
        outs = ["foo.bar"],
        cmd = """
          python3 $(location //src:foo_tool)
          cp foo.bar $@
        """,
        tools = [":foo_tool"],
    )
    

    注意 genrule 命令中所需的副本。如果您的 python 脚本可以输出到标准输出,那就更简洁了,那么您可以将输出重定向到文件而不是添加复制命令。请参阅this 了解更多信息。

    我的输出有这些变化:

    INFO: Analysed target //src:foo_gen (0 packages loaded).
    INFO: Found 1 target...
    Target //src:foo_gen up-to-date:
      bazel-genfiles/src/foo.bar
    INFO: Elapsed time: 0.302s, Critical Path: 0.00s
    INFO: 0 processes.
    INFO: Build completed successfully, 1 total action
    

    【讨论】:

    • 感谢您的回答。但是这种方式下载第三方项目后必须手动更改python脚本,不是很自动化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多