Michael
Michael

Reputation: 4471

Service __len__ not found Unexpected error, recovered safely

python3.8

My code:

from googleads import adwords

def execute_request():
    adwords_client = adwords.AdWordsClient.LoadFromStorage(path="google_general/googleads.yaml")
    campaign_service = adwords_client.GetService('CampaignService', version='v201809')
    pass


context["dict_list"] = execute_request()

Traceback:

Traceback (most recent call last):
  File "/home/michael/pycharm-community-2019.3.2/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_xml.py", line 282, in frame_vars_to_xml
    xml += var_to_xml(v, str(k), evaluate_full_value=eval_full_val)
  File "/home/michael/pycharm-community-2019.3.2/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_xml.py", line 369, in var_to_xml
    elif hasattr(v, "__len__") and not is_string(v):
  File "/home/michael/PycharmProjects/ads3/venv/lib/python3.8/site-packages/googleads/common.py", line 694, in __getattr__
    raise googleads.errors.GoogleAdsValueError('Service %s not found' % attr)
googleads.errors.GoogleAdsValueError: Service __len__ not found
Unexpected error, recovered safely.

googleads.yaml about logging

logging:
  version: 1
  disable_existing_loggers: False
  formatters:
    default_fmt:
      format: ext://googleads.util.LOGGER_FORMAT
    handlers:
      default_handler:
        class: logging.StreamHandler
        formatter: default_fmt
        level: DEBUG
    loggers:
    # Configure root logger
      "":
      handlers: [default_handler]
      level: DEBUG

I've just started studying the API. Namely, I'm trying to execute my first request (https://developers.google.com/adwords/api/docs/guides/first-api-call#make_your_first_api_call)

Could you help me with this problem? At least how to localize it more precisely.

Upvotes: 0

Views: 423

Answers (1)

dorian
dorian

Reputation: 6292

This seems to be a problem which results from the way the PyCharm debugger inspects live objects during debugging.

Specifically, it checks if a given object has the __len__ attribute/method in the code of var_to_xml, most likely to determine an appropriate representation of the object for the debugger interface (which seems to require constructing an XML representation).

googleads service objects such as your campaign_service, however, use some magic to be able to call the defined SOAP methods on them without requiring to hard-code all of them. The code looks like this:

def __getattr__(self, attr):
    """Support service.method() syntax."""
    if self._WsdlHasMethod(attr):
      if attr not in self._method_proxies:
        self._method_proxies[attr] = self._CreateMethod(attr)
      return self._method_proxies[attr]
    else:
      raise googleads.errors.GoogleAdsValueError('Service %s not found' % attr)

This means that the debugger's check for a potential __len__ attribute is intercepted, and because the CampaignService does not have a SOAP operation called __len__, an exception is raised.

You can validate this by running your snippet in the regular way (i.e. not debugging it) and checking if that works.

An actual fix would seem to either require that PyCharm's debugger changes the way it inspects objects (not calling hasattr(v, "__len__")) or that googleads modifies the way it implements __getattr__, for example by actually implementing a __len__ method that just raises AttributeError.

Upvotes: 1

Related Questions