10

I am deploying a Google Cloud Function that will kick off other Google Cloud Functions using google.cloud.pubsub_v1 and I'm getting this error ImportError: cannot import name 'pubsub' from 'google.cloud' (unknown location)

The beginning of my requirements.txt file looks like this

# Function dependencies, for example:
# package>=version
google-cloud-pubsub
....

The beginning of my main.py script looks like this:

import base64
import json
from google.cloud import pubsub_v1

publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path(<PROJECT_ID>, <PUBSUB_TOPIC>)

I am deploying this code from a Google Cloud Source Repository. I have read through this SO post about my error, but that question appears to be about this error arising in a Client application. My error is being generated by the Google Cloud function itself during the deploy process. I don't have sudo rights to the auto-created VM that Google is using to run my process, do I? I should be able to resolve this issue from the requirements.txt file, but nothing I've tried seems to be working.

What's more frustrating is that when I put this same code in the "Inline editor" on the web-based Google Function editor, I don't get an error. I only get this error when loading the code from the repository.

The current file structure in the repository looks something like this:

.
├── package
|   ├── main.py
|   ├── script1.py
|   └── script2.py
├── package2
├── ...
└── requirements.txt

I moved main.py inside of a package because of issues I was having in this SO Question

Any ideas on how to resolve this import error?

Dustin Ingram
  • 20,502
  • 7
  • 59
  • 82
Jed
  • 1,823
  • 4
  • 20
  • 52

2 Answers2

7

Your main.py file and requirements.txt file should be in the same directory, and this should also be the same directory you're deploying your function from.

Also, the google-cloud package is deprecated and shouldn't be used with other google-cloud-* packages. You should remove it from your requirements.txt file.

Dustin Ingram
  • 20,502
  • 7
  • 59
  • 82
  • I get the same error with or without the `google-cloud` package in the `requirements.txt` file. – Jed Sep 24 '18 at 19:46
  • I see you're using Cloud Source Repositories. Are you making sure to re-deploy the function after pushing a new commit to the repository? It won't auto-deploy. – Dustin Ingram Sep 24 '18 at 23:07
  • yes, I push to my repository, then I run the `gcloud deploy ...` command in my terminal and that is when I get this error, during the deployment of the function. – Jed Sep 25 '18 at 00:24
  • Do you have a `lib` folder in your repository that might contain other dependencies? – Dustin Ingram Sep 25 '18 at 15:47
  • Nope, no `lib` folder with other dependencies. – Jed Sep 25 '18 at 15:57
  • Any other ideas of things I should be looking into to resolve this issue? – Jed Sep 25 '18 at 21:54
  • When you're deploying, are you deploying from the same directory as your `requirements.txt` file? – Dustin Ingram Sep 25 '18 at 22:27
  • That did it! The `requirements.txt` file needs to be in the same directory as `main.py`. I moved mine into the `package` directory. Will you update your answer to include this information and I'll mark it as the solution? – Jed Sep 25 '18 at 23:25
0

To install the google-cloud library, you need to perform

pip install google-cloud-storage

as can be seen in the official Google Cloud documentation, so don't install google-cloud-pubsub.

Nevertheless, you import the pubsub package as you did by

from google.cloud import pubsub_v1

Again, a page dedicated for the pubsub_v1 library exists on the official Google Cloud documentation here that shows the following example:

import time

from google.cloud import pubsub_v1

# TODO project_id = "Your Google Cloud Project ID"
# TODO subscription_name = "Your Pub/Sub subscription name"

subscriber = pubsub_v1.SubscriberClient()
# The `subscription_path` method creates a fully qualified identifier
# in the form `projects/{project_id}/subscriptions/{subscription_name}`
subscription_path = subscriber.subscription_path(
    project_id, subscription_name)

def callback(message):
    print('Received message: {}'.format(message))
    message.ack()

subscriber.subscribe(subscription_path, callback=callback)

# The subscriber is non-blocking. We must keep the main thread from
# exiting to allow it to process messages asynchronously in the background.
print('Listening for messages on {}'.format(subscription_path))
while True:
    time.sleep(60)
Agile Bean
  • 6,437
  • 1
  • 45
  • 53