Импорт Bazel Genrule Python из скрипта в другом каталоге
у меня есть Базельnative.genrule
который вызывает скрипт Python для создания файла. В рабочей конфигурации мои файлы следующие:
Python-скрипт:
## test/sub1/test_python_script.py
def test_python_import():
print("this is a function to test function import")
if __name__=="__main__":
test_python_import()
файл
## test/sub1/BUILD
load(":test.bzl", "test_python_import")
filegroup(
name = "test_python_import_script",
srcs = ["test_python_import.py"],
visibility = ["//visibility:public"],
)
test_python_import(
name = "test_python_import",
out_ = "test.txt",
visibility = ["//visibility:public"],
)
test.bzl
файл:
# test/sub1/test.bzl
def test_python_import(
name,
out_ = "",
**kwargs):
native.genrule(
name = name,
outs=[out_,],
cmd = "python3 $(location //project/test/sub1:test_python_import_script) > $(@)",
tools = ["//project/test/sub1:test_python_import_script:test_python_import_script"],
)
Из этого рабочего состояния я хочу переместить функциюtest_python_import()
в другой файл Python, чтобы его можно было использовать и в других сценариях.
Если я создам новый файл (common.py
) в той же подпапкеsub1
, я могу импортировать перемещенные функции в скриптtest_python_import
с:
from common import test_python_import
и все работает, ничего менять не надо.
Если новый скрипт, содержащий определение функции, находится в другой папке, т.е./test/sub2/common.py
:
# test/sub2/common.py
def test_python_import():
print("this is a function to test function import")
и измените исходный скрипт, включив в него эту функцию:
## test/sub1/test_python_script.py
from project.test.sub2 import test_python_import
if __name__=="__main__":
test_python_import()
это не работает. Я попытался добавить файл для использованияfilegroup
и добавьте эту цель в атрибуты и/или макроса bazel:
# test/sub2/BUILD
filegroup(
name = "common_script",
srcs = ["common.py"],
visibility = visibility = ["//visibility:public"],
)
Новое определение макроса
# test/sub1/test.bzl
def test_python_import(
name,
out_ = "",
**kwargs):
native.genrule(
name = name,
outs=[out_,],
srcs = ["//app/test/sub2:common_script",],
cmd = "python3 $(location //app/test/sub1:test_python_import_script) > $(@)",
tools = [
"//app/test/sub1:test_python_import_script",
"//app/test/sub2:common_script",
],
)
но я получаю ошибку
Traceback (most recent call last):
File "app/test/sub1/test_python_import.py", line 1, in <module>
from app.test.sub2 import test_python_import
ModuleNotFoundError: No module named 'app'
Я попытался изменитьtest/sub2/BUILD
файл для определения библиотеки Python, добавив пустой__init__.py
скрипт и модифицируемBUILD
файл на следующее:
# test/sub2/BUILD
py_library(
name = "general_script",
deps = [],
srcs = ["general_script.py"],
visibility = ["//visibility:public"],
)
filegroup(
name = "general_script",
srcs = ["codegen_utils.py"],
visibility = ["//visibility:public"],
)
filegroup(
name = "init",
srcs = ["__init__.py"],
visibility = ["//visibility:public"],
)
а также по-разному модифицировать правило, добавляя и то, и другое кsrcs
иtools
поля цели, определенные в новомapp/test/sub2/common
а затем импортируйте вtest_python_import.py
запишите функцию, но что бы я ни пробовал до сих пор, я продолжаю получать ту же ошибку.
Как импортировать функции, определенные в скрипте, в другой скрипт, находящийся в другом каталоге внутри правила?
1 ответ
Вместо того, чтобы вручную вызыватьpython3 myscript.py
, лучше указать двоичный файл вgenrule.tools
и вызвать это. В этом случае используйтеpy_binary
. Если вам нужна отдельно используемая библиотека, поместите ее вpy_library
и сделать так, чтобы двоичный файл зависел от него. Обратите внимание, что вам может потребоваться установитьpy_library.imports
атрибут, чтобы получить правильные пути к sys.path и импортировать его под нужным именем.
genrule(
cmd = "$(rootpath :mybin) > $(@)"
tools = [":mybin"]
)
py_binary(
name = "mybin",
srcs = ["mybin.py"],
deps = [":mylib"],
)
py_library(name = "mylib", srcs=["mylib.py"])
Обратите внимание, что это обычно справедливо для любого инструмента, который вы используете в правиле — лучше использовать двоичные правила, специфичные для конкретного языка. Это позволяет им собирать исходники в правильный исполняемый файл. Это также уменьшает источник системных зависимостей. например, для того, чтобыcmd = "python3 bla.py"
для работы требуется, чтобы хост-система, на которой выполняется команда, имела совместимую версию python3, доступную по пути в среде оболочки genrule (плюс любые другие зависимости, такие как сторонние библиотеки и т. д.). Например, при использовании py_binary эти зависимости обрабатываются правилом и инфраструктурой Bazel.