Kurt Peek
Kurt Peek

Reputation: 57381

What is the best way to raise request errors?

I'm reading some source code which raises errors for bad requests in the following way:

import requests

response = requests.get("www.google.com")   # This won't work because it's missing the http://
if response.ok is False or response.json()['status'] != 'success':
    raise Exception("API error: {}".format(response.json()['message']))

I was thinking that the last two lines could be replaced with

response.raise_for_status()

I actually don't see any difference in the error returned. In both cases it is

Traceback (most recent call last):
  File "/home/kurt/Documents/Scratch/requests_test.py", line 3, in <module>
    response = requests.get("www.google.com")   # This won't work because it's missing the http://
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/sessions.py", line 451, in request
    prep = self.prepare_request(req)
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/sessions.py", line 382, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/models.py", line 304, in prepare
    self.prepare_url(url, params)
  File "/home/kurt/.local/lib/python2.7/site-packages/requests/models.py", line 362, in prepare_url
    to_native_string(url, 'utf8')))
requests.exceptions.MissingSchema: Invalid URL 'www.google.com': No schema supplied. Perhaps you meant http://www.google.com?

It seems to me that raise_for_status() is more succinct and perhaps also doesn't lose information on the original exception (cf. Use of "except Exception" vs. "except ... raise" in Python). Would this indeed be a better approach?

Upvotes: 0

Views: 2630

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121186

response.raise_for_status() only raises an exception if the response status code is not a 200 response. The second case, where response.json()['status'] != 'success' is true, is not covered.

You have a different error, however. You never get to the if test, because the exception is raised by the requests.get() call. You failed to pass in a schema (no http:// or https:// at the start). Because the exception is raised in the requests.get() expression, the next line is simply never executed. No request is even sent, so you can't make any assertions about the response either.

The test has more problems:

  • requests.ok is False is not idiomatic Python; you'd use not requests.ok instead
  • If requests.ok is False is true, then the requests.json() call will most likely fail altogether, so the next line using response.json()['message']) will produce a different exception.

Upvotes: 4

Related Questions