135

I've got an Nonetype value x, it's generally a number, but could be None. I want to divide it by a number, but Python raises:

TypeError: int() argument must be a string or a number, not 'NoneType'

How can I solve this?

martineau
  • 119,623
  • 25
  • 170
  • 301
user469652
  • 48,855
  • 59
  • 128
  • 165
  • 7
    Assume that None is equivalent to 2771. But maybe that's not what you want. Please give more information. – JoshD Oct 14 '10 at 04:59
  • Somehow I got an Nonetype value, it supposed to be an int, but it's now a Nonetype object, and I need to divide another number, then the error came up. – user469652 Oct 14 '10 at 05:01
  • `int(None)` throws an exception because None can't be converted to an int. The answer to your question is it can't be done. You can substitute something, like 0, or 2771, or a pink elephant, but whatever you substitute, you still won't be able to convert None to an int. – snapshoe Oct 14 '10 at 05:17
  • 8
    @ma3204. converting `None` to a pink elephant is no good either, unless you're working some number system that formally defines division of a number by a pink elephant (and you've written the code to back it up) – aaronasterling Oct 14 '10 at 05:22
  • I am using pyudev and get returned a value which when printed looks like '12d4' which corresponds to a USB VID. However, the type(value) is NoneType. How can a variable that has a value be a NoneType? And I get the same error as above. when I try and do int() on the value. – Brian Reinhold Jul 14 '22 at 21:18

10 Answers10

420
int(value or 0)

This will use 0 in the case when you provide any value that Python considers False, such as None, 0, [], "", etc. Since 0 is False, you should only use 0 as the alternative value (otherwise you will find your 0s turning into that value).

int(0 if value is None else value)

This replaces only None with 0. Since we are testing for None specifically, you can use some other value as the replacement.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • 89
    user469652 you should consider making this the accepted answer instead. it's actually helpful as opposed to condescending – galarant Jan 22 '13 at 03:04
  • 1
    i'm not sure if this solves the issue the user is facing ie. use the nonetype to perform a calculation...i'm currently pulling data via a rest api which is returning a nonetype containing a numerical value. If i set it to 0 or leave it as it is i can't do anything with it – br3w5 Dec 31 '13 at 17:13
  • 2
    This is defiantly the best answer, given the question, as the user indicate that None, should be expected, like possibly a function, requesting the value of something returning None to indicate the value is unknown it this case the None should become the default value in its usage case, which would usually be 0. consider izip_longest, default argument, it the different one have a different default (even type), then the default should be None which is then replace with a default, however string.(str, w) only takes an integer for width. – Glen Fletcher Apr 29 '15 at 06:16
  • this is very helpful, neat and smart – Anupam Feb 12 '19 at 09:07
  • 2
    we can use `(value or 0)` -- without the int type casting -- if we assured that value can only be a None or an int – hashlash Jun 14 '19 at 20:16
  • Man this is fantastic info. I needed to convert a bunch of strings to floats and it works great for my application – Kyle Apr 02 '20 at 20:01
57

In one of the comments, you say:

Somehow I got an Nonetype value, it supposed to be an int, but it's now a Nonetype object

If it's your code, figure out how you're getting None when you expect a number and stop that from happening.

If it's someone else's code, find out the conditions under which it gives None and determine a sensible value to use for that, with the usual conditional code:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...or even...

if x == THING_THAT_RESULTS_IN_NONE:
    result = DEFAULT_VALUE
else:
    result = could_return_none(x) # But it won't return None, because we've restricted the domain.

There's no reason to automatically use 0 here — solutions that depend on the "false"-ness of None assume you will want this. The DEFAULT_VALUE (if it even exists) completely depends on your code's purpose.

detly
  • 29,332
  • 18
  • 93
  • 152
  • 7
    +1 for the "right" solution. If your window often breaks mysteriously, figure out why (and catch the vandal who's responsible) instead of blocking the window up ;) –  Oct 14 '10 at 07:59
  • 4
    This is not useful in case you are retrieving keys from a redis dictionary for example, as the missing keys will be None. If you want to sum them regardless of their presence (which is totally acceptable behavior), you may need to convert None to 0 (see kindall answer) – spider Nov 28 '13 at 17:02
  • 1
    @spider - that still means it's highly dependent on the situation, and "determine a sensible value" still applies. – detly Nov 28 '13 at 21:08
  • Spider's point is quite valid this answer basically just says you did something wrong, but None doesn't mean that it means unknown value, that could indicate you did something wrong, or as spider suggested a missing value, in general it should be come 0 or possibly 1, for most possible uses of None where an integer is expected. – Glen Fletcher Apr 29 '15 at 06:21
  • @glenflet If you don't know what the input domain and specification of your function is, a stranger on the internet isn't going to be able to tell you. If you do know, but don't know the syntax for converting it, that's a completely different question to the one asked here. – detly Apr 29 '15 at 07:26
19

A common "Pythonic" way to handle this kind of situation is known as EAFP for "It's easier to ask forgiveness than permission". Which usually means writing code that assumes everything is fine, but then wrapping it with a try...except block to handle things—just in case—it's not.

Here's that coding style applied to your problem:

try:
    my_value = int(my_value)
except TypeError:
    my_value = 0  # or whatever you want to do

answer = my_value / divisor

Or perhaps the even simpler and slightly faster:

try:
    answer = int(my_value) / divisor
except TypeError:
    answer = 0

The inverse and more traditional approach is known as LBYL which stands for "Look before you leap" is what @Soviut and some of the others have suggested. For additional coverage of this topic see my answer and associated comments to the question Determine whether a key is present in a dictionary elsewhere on this site.

One potential problem with EAFP is that it can hide the fact that something is wrong with some other part of your code or third-party module you're using, especially when the exceptions frequently occur (and therefore aren't really "exceptional" cases at all).

martineau
  • 119,623
  • 25
  • 170
  • 301
14

In Python 3 you can use the "or" keyword too. This way:

foo = bar or 0
foo2 = bar or ""
Ferrarezi
  • 801
  • 10
  • 12
  • 1
    This is it. This is the correct solution! – Ulf Aslak Aug 31 '21 at 09:41
  • This won't work if 0 is a valid value for 'bar', as it will also evaluate to False. In such a case, 'foo2' will become an empty string instead of the integer 0. – bavaza Mar 19 '22 at 07:55
12

That TypeError only appears when you try to pass int() None (which is the only NoneType value, as far as I know). I would say that your real goal should not be to convert NoneType to int or str, but to figure out where/why you're getting None instead of a number as expected, and either fix it or handle the None properly.

martineau
  • 119,623
  • 25
  • 170
  • 301
waffle paradox
  • 2,755
  • 18
  • 19
3

I've successfully used int(x or 0) for this type of error, so long as None should equate to 0 in the logic. Note that this will also resolve to 0 in other cases where testing x returns False. e.g. empty list, set, dictionary or zero length string. Sorry, Kindall already gave this answer.

user3109122
  • 81
  • 1
  • 1
1

I was having the same problem using the python email functions. Below is the code I was trying to retrieve email subject into a variable. This works fine for most emails and the variable populates. If you receive an email from Yahoo or the like and the sender did no fill out the subject line Yahoo does not create a subject line in the email and you get a NoneType returned from the function. Martineau provided a correct answer as well as Soviut. IMO Soviut's answer is more concise from a programming stand point; not necessarily from a Python one. Here is some code to show the technique:

import sys, email, email.Utils 

afile = open(sys.argv[1], 'r')    
m = email.message_from_file(afile)    
subject = m["subject"]

# Soviut's Concise test for unset variable.

if subject is None:    
     subject = "[NO SUBJECT]"

# Alternative way to test for No Subject created in email (Thanks for NoneThing Yahoo!)

try:    
    if len(subject) == 0:    
        subject = "[NO SUBJECT]"

except TypeError:    
    subject = "[NO SUBJECT]"

print subject

afile.close()
1

You should check to make sure the value is not None before trying to perform any calculations on it:

my_value = None
if my_value is not None:
    print int(my_value) / 2

Note: my_value was intentionally set to None to prove the code works and that the check is being performed.

Soviut
  • 88,194
  • 49
  • 192
  • 260
  • 1
    you should use the identity comparison (`is [not] None`) – shylent Oct 14 '10 at 05:37
  • -4 You should be encouraging the OP to find out what his real problem is instead of avoiding it. What @shylent said. You set `my_value` unconditionally to None; why? You don't question why the OP thinks he needs to do `int(my_value)` when `my_value` is (if not None) "generally a number". – John Machin Oct 14 '10 at 06:34
  • 1
    I set my_value to None as a proof of concept, to show my code doesn't fail. I didn't question the OP because there are many reasons why a value may not always be a number and checking that it is before performing calculations is a good idea. There's nothing wrong with simply answering the OP's question, I don't have to do all their homework for them. – Soviut Oct 14 '10 at 07:37
1

This can happen if you forget to return a value from a function: it then returns None. Look at all places where you are assigning to that variable, and see if one of them is a function call where the function lacks a return statement.

Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
1

In some situations it is helpful to have a function to convert None to int zero:

def nz(value):

    '''
    Convert None to int zero else return value.
    '''

    if value == None:
        return 0
    return value