How to let a list append "nothing" (NOT NULL VALUE)
Question:
I have a function that will return different values depending on an if statement in the function. The returned value will be added to an existing list. However, in the function there is a case where I want the function to do nothing, i.e., the existing list will keep the same as if no function were called. Currently what I’m doing is the following, but I feel this looks messy and wondering if there is a better way to do:
import requests
def myfun(url):
response=requests.get(url)
code=response.status_code
if code==503:
time.sleep(3*random.random())
value=None
else:
html=response.content()
value=html['some tag']
return (value,code)
lists=[]
for url in [my url pool]:
(value,code)=myfun(url)
lists.append(value)
if code==503:
lists.pop()
So basically what I do is to continuously visit some webpage, read some values then put the values in a growing list. However, sometime I get blocked (where Error Code 503 is given), then I want my code to sleep for a while then keep moving forward. In the case where I get 503 error code, nothing will be returned so the growing list will be the same. But I don’t know how to specify this case when I call the function, so I just set the returned values to None (or could be any value), then add them to the list but remove them from the list right after that. (So I use append() then pop() if the code is 503)
Answers:
Instead of appending the value, then checking for a 503 and removing the value…
lists.append(value)
if code==503:
lists.pop()
Check that the response is not 503 and then append the value.
if code!=503:
lists.append(value)
There are plenty of options; if you do care about the code, use the solution by @TigerhawkT3; if all you need is to append one value or none, you can e.g. just return None
(and test for it), or return a (potentially empty) list, and .extend
rather than .append
The latter option opens door to a particularly concise (while still readable) code:
import requests
def myfun(url):
response=requests.get(url)
code=response.status_code
if code==503:
## why? time.sleep(3*random.random())
return []
else:
html=response.content()
return [html['some tag']]
lists=[value for url in [my url pool] for value in myfun(url)]
In Python, None
is used to indicate no value. It is the same as NULL
in other languages.
In your scenario, the correct application would be to add None
when 503 is returned.
Ideally, you should return None
and whatever error code is returned – as I assume the remainder of your code should fail if say, a 500 error is raised instead.
Once you have looped through all the URLs, simply filter out the ones that were successful; this way you can later decide what you do with that data (for example, log them separately or queue them for another run, etc).
Here is an approach that doesn’t discard “invalids”, but simply filters them out:
def myfun(url):
value = None
response=requests.get(url)
code=response.status_code
if code > 400:
time.sleep(3*random.random())
return (value, code)
else:
html=response.content()
value=html['some tag']
return (value,code)
lists=[]
for url in [my url pool]:
lists.append(myfun(url))
# you can also do
lists = [myfun(url) for url in my_url_pool]
successful = filter(lists, key=lambda x: x[0] != None)
blocked = filter(lists, key=lambda x: x[0] == 503)
I had a weird case where I needed to append nothing, and I just used the increment operator
a += []
I have a function that will return different values depending on an if statement in the function. The returned value will be added to an existing list. However, in the function there is a case where I want the function to do nothing, i.e., the existing list will keep the same as if no function were called. Currently what I’m doing is the following, but I feel this looks messy and wondering if there is a better way to do:
import requests
def myfun(url):
response=requests.get(url)
code=response.status_code
if code==503:
time.sleep(3*random.random())
value=None
else:
html=response.content()
value=html['some tag']
return (value,code)
lists=[]
for url in [my url pool]:
(value,code)=myfun(url)
lists.append(value)
if code==503:
lists.pop()
So basically what I do is to continuously visit some webpage, read some values then put the values in a growing list. However, sometime I get blocked (where Error Code 503 is given), then I want my code to sleep for a while then keep moving forward. In the case where I get 503 error code, nothing will be returned so the growing list will be the same. But I don’t know how to specify this case when I call the function, so I just set the returned values to None (or could be any value), then add them to the list but remove them from the list right after that. (So I use append() then pop() if the code is 503)
Instead of appending the value, then checking for a 503 and removing the value…
lists.append(value)
if code==503:
lists.pop()
Check that the response is not 503 and then append the value.
if code!=503:
lists.append(value)
There are plenty of options; if you do care about the code, use the solution by @TigerhawkT3; if all you need is to append one value or none, you can e.g. just return None
(and test for it), or return a (potentially empty) list, and .extend
rather than .append
The latter option opens door to a particularly concise (while still readable) code:
import requests
def myfun(url):
response=requests.get(url)
code=response.status_code
if code==503:
## why? time.sleep(3*random.random())
return []
else:
html=response.content()
return [html['some tag']]
lists=[value for url in [my url pool] for value in myfun(url)]
In Python, None
is used to indicate no value. It is the same as NULL
in other languages.
In your scenario, the correct application would be to add None
when 503 is returned.
Ideally, you should return None
and whatever error code is returned – as I assume the remainder of your code should fail if say, a 500 error is raised instead.
Once you have looped through all the URLs, simply filter out the ones that were successful; this way you can later decide what you do with that data (for example, log them separately or queue them for another run, etc).
Here is an approach that doesn’t discard “invalids”, but simply filters them out:
def myfun(url):
value = None
response=requests.get(url)
code=response.status_code
if code > 400:
time.sleep(3*random.random())
return (value, code)
else:
html=response.content()
value=html['some tag']
return (value,code)
lists=[]
for url in [my url pool]:
lists.append(myfun(url))
# you can also do
lists = [myfun(url) for url in my_url_pool]
successful = filter(lists, key=lambda x: x[0] != None)
blocked = filter(lists, key=lambda x: x[0] == 503)
I had a weird case where I needed to append nothing, and I just used the increment operator
a += []