google / subpar

Subpar is a utility for creating self-contained python executables. It is designed to work well with Bazel.
Apache License 2.0
567 stars 69 forks source link

Cannot execute par containing grpcio #82

Open pjachowi opened 6 years ago

pjachowi commented 6 years ago

When I run .par file built with par_binary, I receive following error

$ bazel-bin/client.par
Traceback (most recent call last):
  File "/home/pjachowi/anaconda3/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/home/pjachowi/anaconda3/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "bazel-bin/client.par/__main__.py", line 6, in <module>
  File "bazel-bin/client.par/pypi__grpcio_1_6_0/grpc/__init__.py", line 22, in <module>
ImportError: cannot import name 'cygrpc'

Here is my hello-world project:

$ cat WORKSPACE 
#load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
  name = "org_pubref_rules_protobuf",
  remote = "https://github.com/pubref/rules_protobuf",
  tag = "v0.8.2",
)

load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories")
py_proto_repositories()

# ================================================================
# Python GRPC support requires rules_python
# ================================================================
load("@org_pubref_rules_protobuf//protobuf:rules.bzl", "github_archive")
github_archive(
    name = "io_bazel_rules_python",
    commit = "8b5d0683a7d878b28fffe464779c8a53659fc645",
    org = "bazelbuild",
    repo = "rules_python",
    sha256 = "40499c0a9d55f0c5deb245ed24733da805f05aaf6085cb39027ba486faf1d2e1",
)

load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import")

pip_repositories()

pip_import(
   name = "pip_grpcio",
   # requirements = "//third_party:grpcio_requirements.txt",
   requirements = "@org_pubref_rules_protobuf//python:requirements.txt",
)

load("@pip_grpcio//:requirements.bzl", pip_grpcio_install = "pip_install")

pip_grpcio_install()

# ================================================================
# Support for par - python archives
# ================================================================
git_repository(
    name = "subpar",
    remote = "https://github.com/google/subpar",
    tag = "1.0.0",
)
$ cat BUILD 
package(default_visibility = ["//visibility:public"])

load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library")
load("@subpar//:subpar.bzl", "par_binary")
load("@pip_grpcio//:requirements.bzl", "requirement")

proto_library(
  name = "hello_proto",
  srcs = ["hello.proto"],
)

py_proto_library(
  name = "hello_py_proto",
  protos = ["hello.proto"],
  py_proto_deps = [
    "hello_proto",
  ],
)

par_binary(
  name = "client",
  srcs = ["client.py"],
  deps = [":hello_py_proto",
        requirement("grpcio"),
        requirement("protobuf"),
    ],
)
$ cat hello.proto 
syntax = "proto3";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
$ cat client.py 
import grpc
import hello_pb2
import hello_pb2_grpc

class Greeter(hello_pb2_grpc.GreeterServicer):

  def SayHello(self, request, context):
    return hello_pb2.HelloReply(message='Hello, %s!' % request.name)

  def SayHelloAgain(self, request, context):
    return hello_pb2.HelloReply(message='Hello again, %s!' % request.name)

To my surprise, when I unzip client.par and invoke PYTHONPATH=. python ./__main__.py it works fine.

akirchhoff-modular commented 5 years ago

grpcio is not ZIP-safe. You must use zip_safe = False on all PARs that depend on grpcio.