1014

Is there a way to check if the type of a variable in python is a string, like:

isinstance(x,int);

for integer values?

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
c_pleaseUpvote
  • 10,173
  • 3
  • 15
  • 6

22 Answers22

1508

In Python 3.x, the correct way to check if s is a string is

isinstance(s, str)

The bytes class isn't considered a string type in Python 3.


In Python 2.x, the correct check was

isinstance(s, basestring)

basestring is the abstract superclass of str and unicode. It can be used to test whether an object is an instance of either str or unicode.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 12
    @Yarin: No. But it doesn't matter, because Python 3.x is not meant to be compatible with Python 2.x at all. – netcoder Jul 15 '13 at 17:45
  • 2
    I found that isinstance(s, str) works with py27, tested on : Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin. – kakyo Jan 16 '14 at 21:38
  • 26
    @kakyo: The problem is that it will miss `unicode` objects, which should also be considered strings. Both the type `str` and the type `unicode` have the common base class `basestring`, and this is what you want to check for. – Sven Marnach Jan 16 '14 at 21:41
  • 7
    @Yarin if you're porting something from 2.x to 3.x, you can always assign `basestring = str`. – Jacklynn Apr 20 '15 at 23:50
  • 10
    @AdamErickson For compatibility with what exactly? It doesn't help for compatibility with Python 3, since there is no `unicode` in Python 3. My recommendation for compatibility between Python 2 and 3 is to use the "six" library. (Specifically `isintance(s, six.string_types)` in this case) – Sven Marnach Aug 12 '16 at 14:55
  • I get `UnboundLocalError: local variable 'str' referenced before assignment` when I use `isinstance(s, str)` with python 3.9 – msoutopico Feb 21 '21 at 13:07
  • 1
    @msoutopico This means you use `str` as the name of a local variable later in your function, shadowing the builtin with the same name. Don't do that, just rename it to something else. – Sven Marnach Feb 22 '21 at 08:25
  • @SvenMarnach I think I don't do that. The issue got fixed, indirectly. I think the reason for that error was that I was trying to convert to string (i.e. `str(x)`) something (`x`) that was `nan` (extracted from an empty cell in a spreadsheet). Thanks for your help. – msoutopico Feb 24 '21 at 08:52
  • 1
    @msoutopico No, that's not a possible explanation. The given error message can only possibly occur when the compiler infers that `str` is the name of a local variable. This is inferred statically, at compile time, so invalid values at runtime do not matter. – Sven Marnach Feb 25 '21 at 09:29
241

I know this is an old topic, but being the first one shown on google and given that I don't find any of the answers satisfactory, I'll leave this here for future reference:

six is a Python 2 and 3 compatibility library which already covers this issue. You can then do something like this:

import six

if isinstance(value, six.string_types):
    pass # It's a string !!

Inspecting the code, this is what you find:

import sys

PY3 = sys.version_info[0] == 3

if PY3:
    string_types = str,
else:
    string_types = basestring,
André Fratelli
  • 5,920
  • 7
  • 46
  • 87
  • 6
    E.g. for a one liner: `value_is_string = isinstance(value, str if sys.version_info[0] >= 3 else basestring)`, where `>=` assumes any eventual Python 4+ keeps the `str` root class for strings. – Pi Marillion Oct 22 '16 at 13:13
  • 2
    six is not a part of the standard Python install, so almost by definition is non-portable. I want to write a simple Python app and have it "just work" for anybody who runs it. If I tell them "first, you need to install this *other* library just use my app", that's a big problem. – Edward Falk Aug 07 '21 at 20:27
  • That's why the implementation code is there. – André Fratelli Aug 10 '21 at 10:42
  • The `six` library seems to be available only for Python2 on my Mac. If its availability is version-specific, you might as well use one of the version-specific solutions in the first place. – Edward Falk Sep 16 '21 at 19:52
  • What the code expands into is written there. You can just use that. The point is that other answers here are wrong, according to what the Python library considers a string type. – André Fratelli Feb 17 '22 at 18:35
113

In Python 3.x or Python 2.7.6

if type(x) == str:
Texom512
  • 4,785
  • 3
  • 16
  • 16
  • 12
    I like the elegance of "if type(x) in (str, unicode):", but I see PyLint flags it as "unidiomatic". – eukras Dec 22 '15 at 18:12
  • 41
    Comparing types with `==` is explicitly discouraged by PEP8, and has several downsides in addition to be considered "unidiomatic", e.g. it does not detect instances of subclasses of `str`, which should be considered strings as well. If you really want to check for exactly the type `str` and explicitly exclude subclasses, use `type(x) is str`. – Sven Marnach Oct 28 '17 at 14:03
  • @SvenMarnach So should isinstance be used instead to include the subclasses? – sinekonata Mar 20 '21 at 21:56
  • 3
    @sinekonata Yes, the most common and recommended way to check for strings is `isinstance(s, str)` in Python 3.x – see my answer above. Only if you have a specific reason to exclude subclasses (which should be rare), you should use `type(s) is str`. – Sven Marnach Mar 21 '21 at 09:59
  • `type(x) == str` doesn't work for unicode strings in Python2. `type(x) in (str, unicode)` is an error in Python3. – Edward Falk Aug 07 '21 at 20:30
26

you can do:

var = 1
if type(var) == int:
   print('your variable is an integer')

or:

var2 = 'this is variable #2'
if type(var2) == str:
    print('your variable is a string')
else:
    print('your variable IS NOT a string')

hope this helps!

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
F. Taylor
  • 503
  • 1
  • 5
  • 10
  • 1
    Better to use something as `type(var) is int`, as using `==` to compare types is not recommended by PEP8 – xCovelus Dec 02 '20 at 09:05
22

Use type() or isinstance()

I don't know why not a single answer before me contains this simple type(my_variable) is str syntax, but using type() like this seems the most-logical and simple to me, by far:

(tested in Python3):

# Option 1: check to see if `my_variable` is of type `str`
type(my_variable) is str

# Option 2: check to see if `my_variable` is of type `str`, including
# being a subclass of type `str` (ie: also see if `my_variable` is any object 
# which inherits from `str` as a parent class)
isinstance(my_variable, str)

The Python type() built-in function documentation is here: https://docs.python.org/3/library/functions.html#type. It states, in part, the following. Notice the note about isinstance():

class type(object)
class type(name, bases, dict, **kwds)

With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.

The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.

So, if you're checking the type of a class object instead of a simple variable, and you need to take subclasses into account, then use isinstance() instead. See its documentation here: https://docs.python.org/3/library/functions.html#isinstance.

Example code:

my_str = "hello"
my_int = 7

print(type(my_str) is str)
print(type(my_int) is str)

print()
print(isinstance(my_str, str))
print(isinstance(my_int, str))

Output:

True
False

True
False
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
14

The type module also exists if you are checking more than ints and strings. http://docs.python.org/library/types.html

dicato
  • 684
  • 4
  • 13
13

Edit based on better answer below. Go down about 3 answers and find out about the coolness of basestring.

Old answer: Watch out for unicode strings, which you can get from several places, including all COM calls in Windows.

if isinstance(target, str) or isinstance(target, unicode):
Wade Hatler
  • 1,785
  • 20
  • 18
  • 1
    Good catch. I didn't know about basestring. It's mentioned about 3 posts down and seems like a better answer. – Wade Hatler Feb 19 '14 at 17:26
  • 7
    `isinstance()` also takes a *tuple* as the second argument. So even if `basestring` did not exist, you could just use `isinstance(target, (str, unicode))`. – Martijn Pieters Jun 13 '15 at 15:22
  • 5
    In python 3.5.1, `unicode` does not appear to be defined: `NameError: name 'unicode' is not defined` – Eric Hu Feb 19 '16 at 13:32
13

since basestring isn't defined in Python3, this little trick might help to make the code compatible:

try: # check whether python knows about 'basestring'
   basestring
except NameError: # no, it doesn't (it's Python3); use 'str' instead
   basestring=str

after that you can run the following test on both Python2 and Python3

isinstance(myvar, basestring)
umläute
  • 28,885
  • 9
  • 68
  • 122
11

Python 2 / 3 including unicode

from __future__ import unicode_literals
from builtins import str  #  pip install future
isinstance('asdf', str)   #  True
isinstance(u'asdf', str)  #  True

http://python-future.org/overview.html

crizCraig
  • 8,487
  • 6
  • 54
  • 53
  • 1
    Thanks a lot! There are dozens of various answers around the internet but the only good is this one. The first line makes `type('foo')` being `unicode` by default in python 2, and the second one make `str` being instance of `unicode`. Thoses makes the code valid in Python 2 and 3. Thanks again ! – Narann Oct 08 '19 at 08:35
10

Lots of good suggestions provided by others here, but I don't see a good cross-platform summary. The following should be a good drop in for any Python program:

def isstring(s):
    # if we use Python 3
    if (sys.version_info[0] >= 3):
        return isinstance(s, str)
    # we use Python 2
    return isinstance(s, basestring)

In this function, we use isinstance(object, classinfo) to see if our input is a str in Python 3 or a basestring in Python 2.

duanev
  • 936
  • 13
  • 17
  • 2
    This will likely break in Python 4, consider `>=` at least. – thakis Dec 15 '16 at 22:08
  • 2
    be cleaner to check for six.string_types or six.text_type – daonb Jan 03 '17 at 12:39
  • 1
    @daonb importing an entire module just to do a one-line test is the thinking that causes crazy dependency trees and serious bloat to ruin what should be something short small and simple. It's your call of course, but just say'n ... – duanev Jan 14 '17 at 21:55
  • @duanev if you're worried about Python 2/3 compatibility it's a better idea to be using six in the project anyways. Six is also a *single file* so dependency trees / bloat are not an issue here. – MoxieBall May 24 '18 at 15:24
  • Also, at least on my Mac, `import six` is an error in Python3 – Edward Falk Sep 16 '21 at 19:59
9

So,

You have plenty of options to check whether your variable is string or not:

a = "my string"
type(a) == str # first 
a.__class__ == str # second
isinstance(a, str) # third
str(a) == a # forth
type(a) == type('') # fifth

This order is for purpose.

PatNowak
  • 5,721
  • 1
  • 25
  • 31
  • This is a good compendium of ways to test a type. However in Python2, if you consider unicode to be a string type, this won't work. – Edward Falk Sep 16 '21 at 19:58
8

Also I want notice that if you want to check whether the type of a variable is a specific kind, you can compare the type of the variable to the type of a known object.

For string you can use this

type(s) == type('')
Daniil Grankin
  • 3,841
  • 2
  • 29
  • 39
  • 9
    This is a terrible, terrible way to type check in python. What if another class inherits from `str`? What about unicode strings, which don't even inherit from `str` in 2.x? Use `isinstance(s, basestring)` in 2.x, or `isinstance(s, str)` in 3.x. – Jacklynn Apr 20 '15 at 23:54
  • 2
    @Jack, please read question, and also notice I do not write that it's the best way, just another way. – Daniil Grankin Apr 24 '15 at 13:41
  • 10
    This is a bad idea for 3 reasons: `isinstance()` allows for subclasses (which are strings too, just specialised), the extra `type('')` call is redundant when you can just use `str` and types are singletons, so `type(s) is str` is going to be a more efficient test. – Martijn Pieters Jun 13 '15 at 15:15
6

Alternative way for Python 2, without using basestring:

isinstance(s, (str, unicode))

But still won't work in Python 3 since unicode isn't defined (in Python 3).

yprez
  • 14,854
  • 11
  • 55
  • 70
6

Here is my answer to support both Python 2 and Python 3 along with these requirements:

  • Written in Py3 code with minimal Py2 compat code.
  • Remove Py2 compat code later without disruption. I.e. aim for deletion only, no modification to Py3 code.
  • Avoid using six or similar compat module as they tend to hide away what is trying to be achieved.
  • Future-proof for a potential Py4.

import sys
PY2 = sys.version_info.major == 2

# Check if string (lenient for byte-strings on Py2):
isinstance('abc', basestring if PY2 else str)

# Check if strictly a string (unicode-string):
isinstance('abc', unicode if PY2 else str)

# Check if either string (unicode-string) or byte-string:
isinstance('abc', basestring if PY2 else (str, bytes))

# Check for byte-string (Py3 and Py2.7):
isinstance('abc', bytes)
Cas
  • 6,123
  • 3
  • 36
  • 35
5
a = '1000' # also tested for 'abc100', 'a100bc', '100abc'

isinstance(a, str) or isinstance(a, unicode)

returns True

type(a) in [str, unicode]

returns True

be_good_do_good
  • 4,311
  • 3
  • 28
  • 42
1

If you do not want to depend on external libs, this works both for Python 2.7+ and Python 3 (http://ideone.com/uB4Kdc):

# your code goes here
s = ["test"];
#s = "test";
isString = False;

if(isinstance(s, str)):
    isString = True;
try:
    if(isinstance(s, basestring)):
        isString = True;
except NameError:
    pass;

if(isString):
    print("String");
else:
    print("Not String");
mPrinC
  • 9,147
  • 2
  • 32
  • 31
1

You can simply use the isinstance function to make sure that the input data is of format string or unicode. Below examples will help you to understand easily.

>>> isinstance('my string', str)
True
>>> isinstance(12, str)
False
>>> isinstance('my string', unicode)
False
>>> isinstance(u'my string',  unicode)
True
Hassan Mehmood
  • 1,414
  • 1
  • 14
  • 22
0

Summarizing:

There doesn't seem to be a portable way to do it if you want both Python2 and Python3, and want to include unicode as well. I wound up using this idiom:

# Near the top of my program
if sys.version_info[0] >= 3:
    basestring = str

Then any time I want to test an object to see if it's a string:

if isinstance(obj, basestring):
    ...

Frankly, I'm a little shocked that Python3 dropped basestring as well as types.StringTypes. I see no reason to drop them, and keeping either of them would have made this problem solveable.

Edward Falk
  • 9,991
  • 11
  • 77
  • 112
-2
s = '123'
issubclass(s.__class__, str)
vadim vaduxa
  • 221
  • 6
  • 16
-6

This is how I do it:

if type(x) == type(str()):
User
  • 23,729
  • 38
  • 124
  • 207
-8

I've seen:

hasattr(s, 'endswith') 
fast tooth
  • 2,317
  • 4
  • 25
  • 34
-14
>>> thing = 'foo'
>>> type(thing).__name__ == 'str' or type(thing).__name__ == 'unicode'
True
Richard Urban
  • 339
  • 3
  • 7
  • 4
    In which case would you prefer `type(thing).__name__ == 'str'` over `type(thing) == str` or `isinstance(thing, str)`? Also `unicode` does not exist in modern versions of Python. – vaultah Jan 12 '18 at 13:06