Repository: googleapis/google-cloud-python

Issue:
Exception in subscribe_experimental - google cloud pubsub 0.34.0
Hi, getting an exception in 0.34.0:

```
[2018-05-13 12:30:14,744 - ERROR - Thread-17 - _channel] Exception iterating requests!
Traceback (most recent call last):
  File "/Users/alonshomrat/Library/Python/2.7/lib/python/site-packages/grpc/_channel.py", line 187, in consume_request_iterator
    request = next(request_iterator)
  File "/Users/alonshomrat/Library/Python/2.7/lib/python/site-packages/google/cloud/pubsub_v1/subscriber/_protocol/bidi.py", line 100, in __iter__
    yield self._initial_request()
  File "/Users/alonshomrat/Library/Python/2.7/lib/python/site-packages/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py", line 313, in _get_initial_request
    lease_ids = self._leaser.ack_ids
AttributeError: 'NoneType' object has no attribute 'ack_ids'
```
I think it's the CleanupThread.

Created a script to reproduce:

1.  Create topic
2. Insert message to it.
3. Create subscription.
4. Start subscribe.
5. Get exception (CleanupThread in _channel -> grpc package).

```
# Create a topic
# Insert data to the topic
# Create subscription and connect it to the topic
# Start subscriber
# Get exception
from google.cloud.pubsub_v1 import PublisherClient, SubscriberClient

publisher_obj = PublisherClient()
subscriber_obj = SubscriberClient()
topics_path = [u'projects/your-project-name/topics/topic_general']
subscribers_path = [u'projects/your-project-name/subscriptions/instance_general']

def create_topics():
    for topic in topics_path:
        try:
            publisher_obj.create_topic(topic)
        except Exception as e:
            print("Topic {}: {}. Notice: don't forget to run pubsub emulator before".format(topic, e.message))

def publish_messages(data, message_type):
    response = publisher_obj.publish(topics_path[0], data=data, type=message_type)
    return response

def create_subscriptions():
    subscriptions = []
    for subscribe, topic in zip(subscribers_path, topics_path):
        subscriptions.append(subscriber_obj.create_subscription(subscribe, topic))
    return subscriptions

def start_subscribe():
    subscription_path = SubscriberClient().subscription_path("your-project-name", "instance_general")
    _ = SubscriberClient().subscribe_experimental(subscription_path, callback=lambda x: x)

def pubsub_error():

    create_topics()
    a = publish_messages(data='{"key3": "value3", "key2": "value2", "key1": "value1"}', message_type="/webhook/webhook_type")
    create_subscriptions()
    start_subscribe()


if __name__ == "__main__":
    pubsub_error()
```


Rest of the information:

```
$ pip show google-cloud
Name: google-cloud
Version: 0.32.0
Summary: API Client library for Google Cloud
Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python
Author: Google Cloud Platform
Author-email: googleapis-publisher@google.com
License: Apache 2.0
Location: /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages
Requires: google-cloud-videointelligence, google-cloud-trace, google-cloud-bigquery-datatransfer, google-cloud-bigquery, google-cloud-language, google-cloud-datastore, google-cloud-core, google-cloud-storage, google-cloud-vision, google-cloud-logging, google-cloud-pubsub, google-cloud-container, google-cloud-monitoring, google-cloud-runtimeconfig, google-cloud-error-reporting, google-cloud-dns, google-cloud-firestore, google-api-core, google-cloud-resource-manager, google-cloud-translate, google-cloud-spanner, google-cloud-speech, google-cloud-bigtable
Required-by: 

$ pip freeze
analytics==0.6.5
appengine==1.8.0.2
asn1crypto==0.22.0
astroid==1.5.2
backports-abc==0.5
backports.functools-lru-cache==1.3
beautifulsoup4==4.6.0
bitstring==3.1.5
boto==2.48.0
bumpversion==0.5.3
cachetools==2.0.1
certifi==2018.1.18
cffi==1.10.0
chardet==3.0.4
click==6.7
cloud==2.8.5
cognitive-luis==0.1
crypto==1.4.1
cryptography==2.0.3
cycler==0.10.0
dill==0.2.7.1
enum==0.4.6
enum34==1.1.6
expiringdict==1.1.3
ez-setup==0.9
fakeredis==0.9.0
Flask==0.12.2
funcsigs==1.0.2
future==0.16.0
futures==3.2.0
gapic-google-cloud-datastore-v1==0.15.3
gapic-google-cloud-error-reporting-v1beta1==0.15.3
gapic-google-cloud-functions-v1beta2==0.15.3
gapic-google-cloud-language-v1==0.15.3
gapic-google-cloud-logging-v2==0.91.3
gapic-google-cloud-pubsub-v1==0.15.4
gapic-google-logging-v2==0.9.3
gapic-google-pubsub-v1==0.11.1
gax-google-logging-v2==0.8.3
gax-google-pubsub-v1==0.8.3
gcloud==0.18.3
gcs-oauth2-boto-plugin==1.14
google==2.0.1
google-api-core==0.1.4
google-api-python-client==1.6.5
google-api-wrapper==2.0.0a1
google-auth==1.4.1
google-auth-httplib2==0.0.3
google-cloud==0.32.0
google-cloud-bigquery==0.28.0
google-cloud-bigquery-datatransfer==0.1.1
google-cloud-bigtable==0.28.1
google-cloud-container==0.1.0
google-cloud-core==0.28.1
google-cloud-datastore==1.4.0
google-cloud-dns==0.28.0
google-cloud-error-reporting==0.28.0
google-cloud-firestore==0.28.0
google-cloud-language==1.0.1
google-cloud-logging==1.4.0
google-cloud-monitoring==0.28.0
google-cloud-pubsub==0.34.0
google-cloud-resource-manager==0.28.0
google-cloud-runtimeconfig==0.28.1
google-cloud-spanner==0.29.0
google-cloud-speech==0.30.0
google-cloud-storage==1.6.0
google-cloud-trace==0.17.0
google-cloud-translate==1.3.0
google-cloud-videointelligence==1.0.0
google-cloud-vision==0.29.0
google-gax==0.15.16
google-resumable-media==0.3.1
googleapis-common-protos==1.5.3
googlemaps==2.5.1
grpc-google-iam-v1==0.11.4
grpc-google-logging-v2==0.8.1
grpc-google-pubsub-v1==0.11.1
grpcio==1.9.1
gunicorn==19.7.1
httplib2==0.10.3
icalendar==3.11.4
idna==2.6
intervaltree==2.1.0
ipaddress==1.0.18
isort==4.2.5
itsdangerous==0.24
Jinja2==2.9.6
keyring==8.7
keyrings.alt==1.3
lazy-object-proxy==1.3.1
luis==2.0.2
lxml==3.7.2
MarkupSafe==1.0
matplotlib==1.5.3
mixpanel==4.3.2
mixpanel-py-async==0.1.0
mock==2.0.0
Naked==0.1.31
numpy==1.13.1
nydus==0.11.0
oauth2client==3.0.0
olefile==0.44
parsedatetime==2.4
pbr==3.1.1
pep8==1.7.0
Pillow==4.0.0
ply==3.8
proto-google-cloud-datastore-v1==0.90.4
proto-google-cloud-error-reporting-v1beta1==0.15.3
proto-google-cloud-functions-v1beta2==0.15.3
proto-google-cloud-language-v1==0.15.3
proto-google-cloud-logging-v2==0.91.3
proto-google-cloud-pubsub-v1==0.15.4
protobuf==3.5.1
psutil==5.4.3
pubsub==0.1.2
py==1.4.34
pyasn1==0.4.2
pyasn1-modules==0.2.1
pycodestyle==2.3.1
pycparser==2.18
pycrypto==2.6.1
pycurl==7.43.0
pyicloud==0.9.1
Pympler==0.5
pyOpenSSL==17.3.0
pyparsing==2.2.0
pytest==3.1.3
python-dateutil==1.5
python-memcached==1.59
python-telegram-bot==6.1b0
pytz==2018.3
PyYAML==3.12
redis==2.10.5
requests==2.18.4
retry-decorator==1.1.0
rsa==3.4.2
shellescape==3.4.1
singledispatch==3.4.0.3
six==1.10.0
SocksiPy-branch==1.1
sortedcontainers==1.5.7
titlecase==0.10.0
tornado==4.5.1
tornadohttpclient==1.1.3
twx.botapi==3.1.1
tzlocal==1.4
uritemplate==3.0.0
urllib3==1.22
urllib3-mock==0.3.3
virtualenv==15.1.0
webapp2==2.3
WebOb==1.7.3
Werkzeug==0.14.1
wrapt==1.10.10

$ python --version
Python 2.7.13
```


Discussion:

Resolving patch:
diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py
--- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py
+++ b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py
@@ -241,22 +241,26 @@ def open(self, callback):
 
         self._callback = functools.partial(_wrap_callback_errors, callback)
 
-        # Start the thread to pass the requests.
-        self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue)
-        self._dispatcher.start()
-
-        # Start consuming messages.
+        # Create the RPC
         self._rpc = bidi.ResumableBidiRpc(
             start_rpc=self._client.api.streaming_pull,
             initial_request=self._get_initial_request,
             should_recover=self._should_recover)
         self._rpc.add_done_callback(self._on_rpc_done)
+
+        # Create references to threads
+        self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue)
         self._consumer = bidi.BackgroundConsumer(
             self._rpc, self._on_response)
+        self._leaser = leaser.Leaser(self)
+
+        # Start the thread to pass the requests.
+        self._dispatcher.start()
+
+        # Start consuming messages.
         self._consumer.start()
 
         # Start the lease maintainer thread.
-        self._leaser = leaser.Leaser(self)
         self._leaser.start()
 
     def close(self, reason=None):


Test patch: