googleads / googleads-python-lib

The Python client library for Google's Ads APIs
Apache License 2.0
685 stars 975 forks source link

TypeError: cannot use a string pattern on a bytes-like object #254

Closed abeburnett closed 6 years ago

abeburnett commented 6 years ago

Any idea why submitting this JSON/selector gives me the following error? (Note: I've been submitting selectors with this format for months, but only with the recent update of the GoogleAds module have I started getting an error)

The Selector {'ideaType': 'KEYWORD', 'paging': {'numberResults': '199', 'startIndex': '0'}, 'requestType': 'STATS', 'requestedAttributeTypes': ['KEYWORD_TEXT', 'TARGETED_MONTHLY_SEARCHES'], 'searchParameters': [{'queries': ['pentaho', 'pentaho data integration', 'pentaho kettle', 'pentaho community', 'pentaho community edition', 'pentaho report designer', 'pentaho training', 'pentaho tutorial', 'tensorflow', 'tensorflow tutorial', 'google tensorflow', 'tensorflow github', 'tensorflow examples', 'github tensorflow', 'tensorflow rnn', 'tensorflow python', 'udacity tensorflow', 'what is tensorflow', 'tensorflow google', 'learn tensorflow', 'tensorflow book', 'talend', 'talend open studio', 'talend etl', 'talend tutorial', 'talend training', 'learn talend', 'pandas python', 'python pandas', 'pandas library', 'what is pandas python', 'pandas in python', 'pandas tutorial', 'python pandas tutorial', 'pandas python tutorial', 'r programming', 'r language', 'r statistics', 'r tutorial', 'learn r', 'r project', 'what is r', 'r programming language', 'r cran', 'r code', 'r packages', 'project r', 'r statistical software', 'r programming tutorial', 'introduction to r', 'apply r', 'r apply', 'learn r programming', 'r for data science', 'programming in r', 'program r', 'statistics r', 'r programming for data science', 'r language tutorial', 'r analytics', 'r in statistics', 'r data analysis', 'what is r programming', 'programming language r', 'r stats package', 'how to learn r', 'code r', 'language r', 'force.com', 'force com', 'sales force com', 'force com ide', 'what is force com', 'force com platform', 'force com development', 'learn force com', 'force com programming', 'salesforce lightning', 'salesforce apex', 'salesforce development', 'salesforce', 'salesforce com', 'salesforce certification', 'www salesforce com', 'what is salesforce', 'salesforce training', 'salesforce jobs', 'salesforce appexchange', 'salesforce crm', 'salesforce tutorial', 'salesforce service cloud', 'appexchange salesforce', 'www salesforce', 'salesforce wave', 'salesforce foundation', 'salesforce connect', 'salesforce dreamforce', 'salesforce software', 'crm salesforce', 'salesforce cloud', 'salesforce sales cloud', 'salesforce review', 'salesforce products', 'salesforce analytics', 'salesforce database', 'salesforce mobile app', 'salesforce app cloud', 'how to use salesforce', 'salesforce for dummies', 'salesforce platform', 'what is salesforce crm', 'what is salesforce com', 'sitecore', 'sitecore cms', 'sitecore training', 'what is sitecore', 'sitecore tutorial', 'sitecore certification', 'magento', 'magento connect', 'magento 2', 'magento commerce', 'magento marketplace', 'what is magento', 'magento tutorial', 'magento enterprise', 'magento development', 'magento community', 'magento cms', 'magento software', 'magento developer guide', 'magento training', 'magento website development', 'servicenow', 'servicenow training', 'what is servicenow', 'servicenow demo', 'servicenow conference', 'servicenow express', 'servicenow cmdb', 'servicenow discovery', 'servicenow asset management', 'servicenow reporting', 'servicenow orchestration', 'servicenow integration', 'learn servicenow', 'servicenow tutorial', 'servicenow development', 'drupal', 'drupal 8', 'drupal themes', 'what is drupal', 'drupal 7', 'drupal tutorial', 'drupal modules', 'drupal commerce', 'drupal views', 'drupal cms', 'drupal templates', 'drupal webform', 'drupal hosting', 'drupal panels', 'drupal wiki', 'drupal website', 'drupal training', 'learn drupal', 'drupal features', 'drupal security', 'drupal login', 'drupal 7 themes', 'drupal wysiwyg', 'drupal token', 'drupal development', 'drupal ecommerce', 'ruby on rails', 'ruby on rails tutorial', 'what is ruby on rails', 'learn ruby on rails', 'ruby on rails examples', 'ruby on rails book', 'ruby on rails guide', 'sinatra ruby', 'ruby sinatra', 'sinatra framework', 'sinatra tutorial', 'node js', 'node js tutorial', 'what is node js', 'learn node js', 'node js examples', 'node js framework', 'how to use node js', 'what is node js used for', 'getting started with node js', 'node js getting started', 'introduction to node js', 'asp.net', 'asp net 5', 'asp net tutorial'], 'xsi_type': 'RelatedToQuerySearchParameter'}, {'languages': [{'id': '1000'}], 'xsi_type': 'LanguageSearchParameter'}, {'networkSetting': {'targetContentNetwork': False, 'targetGoogleSearch': True, 'targetPartnerSearchNetwork': False, 'targetSearchNetwork': False}, 'xsi_type': 'NetworkSearchParameter'}]}

The Error

`In [18]: stats_page = targeting_idea_service.get(stats_selector)

TypeError Traceback (most recent call last)

in () ----> 1 stats_page = targeting_idea_service.get(stats_selector) /usr/local/lib/python3.5/dist-packages/googleads/common.py in MakeSoapRequest(*args) 777 return soap_service_method( 778 *[_PackForSuds(arg, self.suds_client.factory, --> 779 self._packer) for arg in args]) 780 except suds.WebFault as e: 781 if _logger.isEnabledFor(logging.WARNING): /usr/local/lib/python3.5/dist-packages/suds/client.py in __call__(self, *args, **kwargs) 519 client = clientclass(self.client, self.method) 520 try: --> 521 return client.invoke(args, kwargs) 522 except WebFault as e: 523 if self.faults(): /usr/local/lib/python3.5/dist-packages/suds/client.py in invoke(self, args, kwargs) 579 timer) 580 timer.start() --> 581 result = self.send(soapenv) 582 timer.stop() 583 metrics.log.debug("method '%s' invoked: %s", self.method.name, timer) /usr/local/lib/python3.5/dist-packages/suds/client.py in send(self, soapenv) 611 timer = metrics.Timer() 612 timer.start() --> 613 reply = self.options.transport.send(request) 614 timer.stop() 615 metrics.log.debug('waited %s on server reply', timer) /usr/local/lib/python3.5/dist-packages/googleads/util.py in PatchedHttpTransportSend(self, request) 119 self.proxy = self.options.proxy 120 request.headers.update(u2request.headers) --> 121 suds.transport.http.log.debug('sending:\n%s', request) 122 try: 123 fp = self.u2open(u2request) /usr/lib/python3.5/logging/__init__.py in debug(self, msg, *args, **kwargs) 1265 """ 1266 if self.isEnabledFor(DEBUG): -> 1267 self._log(DEBUG, msg, args, **kwargs) 1268 1269 def info(self, msg, *args, **kwargs): /usr/lib/python3.5/logging/__init__.py in _log(self, level, msg, args, exc_info, extra, stack_info) 1413 record = self.makeRecord(self.name, level, fn, lno, msg, args, 1414 exc_info, func, extra, sinfo) -> 1415 self.handle(record) 1416 1417 def handle(self, record): /usr/lib/python3.5/logging/__init__.py in handle(self, record) 1422 well as those created locally. Logger-level filtering is applied. 1423 """ -> 1424 if (not self.disabled) and self.filter(record): 1425 self.callHandlers(record) 1426 /usr/lib/python3.5/logging/__init__.py in filter(self, record) 708 for f in self.filters: 709 if hasattr(f, 'filter'): --> 710 result = f.filter(record) 711 else: 712 result = f(record) # assume callable - will raise if not /usr/local/lib/python3.5/dist-packages/googleads/util.py in filter(self, record) 300 msg = msg.decode('utf-8') 301 new_arg.message = self._DEVELOPER_TOKEN_SUB.sub( --> 302 self._REDACTED, msg) 303 record.args = (new_arg,) 304 TypeError: cannot use a string pattern on a bytes-like object In [19]: targeting_idea_service.get(stats_selector) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () ----> 1 targeting_idea_service.get(stats_selector) /usr/local/lib/python3.5/dist-packages/googleads/common.py in MakeSoapRequest(*args) 777 return soap_service_method( 778 *[_PackForSuds(arg, self.suds_client.factory, --> 779 self._packer) for arg in args]) 780 except suds.WebFault as e: 781 if _logger.isEnabledFor(logging.WARNING): /usr/local/lib/python3.5/dist-packages/suds/client.py in __call__(self, *args, **kwargs) 519 client = clientclass(self.client, self.method) 520 try: --> 521 return client.invoke(args, kwargs) 522 except WebFault as e: 523 if self.faults(): /usr/local/lib/python3.5/dist-packages/suds/client.py in invoke(self, args, kwargs) 579 timer) 580 timer.start() --> 581 result = self.send(soapenv) 582 timer.stop() 583 metrics.log.debug("method '%s' invoked: %s", self.method.name, timer) /usr/local/lib/python3.5/dist-packages/suds/client.py in send(self, soapenv) 611 timer = metrics.Timer() 612 timer.start() --> 613 reply = self.options.transport.send(request) 614 timer.stop() 615 metrics.log.debug('waited %s on server reply', timer) /usr/local/lib/python3.5/dist-packages/googleads/util.py in PatchedHttpTransportSend(self, request) 119 self.proxy = self.options.proxy 120 request.headers.update(u2request.headers) --> 121 suds.transport.http.log.debug('sending:\n%s', request) 122 try: 123 fp = self.u2open(u2request) /usr/lib/python3.5/logging/__init__.py in debug(self, msg, *args, **kwargs) 1265 """ 1266 if self.isEnabledFor(DEBUG): -> 1267 self._log(DEBUG, msg, args, **kwargs) 1268 1269 def info(self, msg, *args, **kwargs): /usr/lib/python3.5/logging/__init__.py in _log(self, level, msg, args, exc_info, extra, stack_info) 1413 record = self.makeRecord(self.name, level, fn, lno, msg, args, 1414 exc_info, func, extra, sinfo) -> 1415 self.handle(record) 1416 1417 def handle(self, record): /usr/lib/python3.5/logging/__init__.py in handle(self, record) 1422 well as those created locally. Logger-level filtering is applied. 1423 """ -> 1424 if (not self.disabled) and self.filter(record): 1425 self.callHandlers(record) 1426 /usr/lib/python3.5/logging/__init__.py in filter(self, record) 708 for f in self.filters: 709 if hasattr(f, 'filter'): --> 710 result = f.filter(record) 711 else: 712 result = f(record) # assume callable - will raise if not /usr/local/lib/python3.5/dist-packages/googleads/util.py in filter(self, record) 300 msg = msg.decode('utf-8') 301 new_arg.message = self._DEVELOPER_TOKEN_SUB.sub( --> 302 self._REDACTED, msg) 303 record.args = (new_arg,) 304 TypeError: cannot use a string pattern on a bytes-like object`
msaniscalchi commented 6 years ago

Hello,

Thanks for the report! I've been able to reproduce with similar code running on Python 3.5. It looks like the error itself is occurring in _SudsTransportFilter, which filters sensitive information from logs.

That said, this happening now is a bit of a mystery, as we haven't made any recent changes to log filtering. There may be a separate underlying issue.

For now, assuming you won't miss the logs, you can get around this by disabling logs / filters.

Regards, Mark

ddoskind commented 6 years ago

This was introduced in DFP v201802 release. Before, the logging message was always decoded from bytes to str/unicode, while after the change it's assumed that the decoding is only required in Python 2. The logged SOAP responses from suds are still bytes in Python 3, however, which is why the TypeError is raised.

msaniscalchi commented 6 years ago

As an update, we plan on timing this so that it is resolved in the AdWords Sunset release next week.

msaniscalchi commented 6 years ago

This issue should now be resolved.