Skip to main content

How to Resolve Python "NameError: name 'unicode' is not defined"

The NameError: name 'unicode' is not defined is a clear indication that you are running code written for Python 2 in a Python 3 environment. In Python 2, unicode was a distinct built-in type representing Unicode text strings. In Python 3, this type was renamed to str, and the original str type (which represented byte strings in Python 2) was essentially replaced by the bytes type.

This guide explains this fundamental Python 2-to-3 change and shows how to update your code by replacing unicode with the appropriate Python 3 equivalent, usually str.

Understanding the Error: Python 2 unicode vs. Python 3 str

The core difference lies in how Python versions handle text and binary data:

  • Python 2:
    • str: Represented sequences of bytes (8-bit strings). Often used for text, but could lead to encoding issues if non-ASCII characters were involved without proper handling.
    • unicode: Represented sequences of Unicode characters (abstract text). Created using u'...' literals or the unicode() function for decoding byte strings. This was the correct type for handling international text.
  • Python 3:
    • str: Represents sequences of Unicode characters (like Python 2's unicode). This is the standard type for all text. u'...' literals are no longer needed or used.
    • bytes: Represents sequences of bytes (binary data). Created using b'...' literals or by encoding strings (my_str.encode()).
    • The name unicode is gone as a built-in type or function.

The NameError occurs because Python 3 simply does not have a built-in object named unicode.

Cause: Using the Python 2 unicode Name in Python 3

You are running Python 3 code that still uses the name unicode as if it were the Python 2 type or function.

# Error Scenario (in Python 3)
try:
# ⛔️ NameError: name 'unicode' is not defined
# Trying to use the Python 2 unicode() function/type
text = unicode("some string", "utf-8") # Example usage from Python 2
print(text)
except NameError as e:
print(e)

try:
# ⛔️ NameError: name 'unicode' is not defined
# Trying to check type against the Python 2 unicode type
is_text = isinstance("hello", unicode)
print(is_text)
except NameError as e:
print(e)

The direct fix for Python 3 code is to replace occurrences of the name unicode with str.

  • If the original code used unicode(byte_string, encoding) to decode bytes, replace it with str(byte_string, encoding) or, more commonly, byte_string.decode(encoding).
  • If the original code used unicode(object) to get a text representation, replace it with str(object).
  • If the original code used isinstance(obj, unicode) to check for text, replace it with isinstance(obj, str).
# ✅ Corrected Code (Python 3)

# --- Simulating decoding ---
byte_data = b'hello bytes'
encoding = 'utf-8'

# Python 2 way: text = unicode(byte_data, encoding)
# Python 3 way 1: Using str() constructor
text1 = str(byte_data, encoding)

# Python 3 way 2: Using decode() method (more common)
text2 = byte_data.decode(encoding)

print(f"Decoded using str(): '{text1}' (Type: {type(text1)})")
# Output: Decoded using str(): 'hello bytes' (Type: <class 'str'>)
print(f"Decoded using decode(): '{text2}' (Type: {type(text2)})")
# Output: Decoded using decode(): 'hello bytes' (Type: <class 'str'>)


# --- Simulating string conversion ---
number = 123
# Python 2 way: text_num = unicode(number)
# Python 3 way: Using str()
text_num = str(number)
print(f"Number as string: '{text_num}' (Type: {type(text_num)})")
# Output: Number as string: '123' (Type: <class 'str'>)


# --- Simulating type checking ---
my_string = "this is text"
# Python 2 way: is_text = isinstance(my_string, unicode)
# Python 3 way: Using str
is_text = isinstance(my_string, str)
print(f"Is '{my_string}' a string (str)? {is_text}")
# Output: Is 'this is text' a string (str)? True
note

This directly uses Python 3's standard types and methods.

Solution 2: Create a unicode Alias for Compatibility (Less Common)

If you are managing code that needs to run on both Python 2 and Python 3 (a "cross-compatible" codebase), you might see or use a compatibility shim that defines unicode as an alias for str when running in Python 3.

import sys

# ✅ Define 'unicode' as an alias for 'str' only in Python 3+
if sys.version_info[0] >= 3:
unicode = str
# You might also define 'basestring' if needed by older code
# basestring = str
else:
# In Python 2, unicode is already defined
# basestring is also defined
pass

# --- Now code using 'unicode' might work in both versions ---
# Example: Type checking (would work in Py2 and Py3 with the shim)
some_text = "hello"
if isinstance(some_text, unicode): # Uses the alias in Python 3
print(f"\n'{some_text}' is considered unicode/str.")

# Example: Conversion (would work in Py2 and Py3 with the shim)
number = 456
text_version = unicode(number) # Uses the alias in Python 3
print(f"Number converted via alias: '{text_version}' (Type: {type(text_version)})")
# Output (in Py3): Number converted via alias: '456' (Type: <class 'str'>)
note
  • Use Case: This approach is primarily for maintaining older codebases intended to run across Python 2 and 3 without extensive modifications.
  • Recommendation: For new code written purely for Python 3, do not use this alias. Use str directly for clarity and adherence to modern Python standards.

Python 3 Text (str) vs. Binary Data (bytes)

It's essential to understand the clear distinction in Python 3:

  • str: For representing text. All strings are sequences of Unicode characters. Literals are written with '...' or "...".
    text_example = "résumé" # Contains Unicode characters
    print(f"String: {text_example} (Type: {type(text_example)})")
    # Output: String: résumé (Type: <class 'str'>)
  • bytes: For representing binary data (sequences of raw bytes, 0-255). Literals are written with b'...' or b"...". Bytes literals can only contain ASCII-compatible characters directly.
    bytes_example = b'raw data'
    print(f"Bytes: {bytes_example} (Type: {type(bytes_example)})")
    # Output: Bytes: b'raw data' (Type: <class 'bytes'>)

Encoding (str to bytes)

Converting text (str) to binary data (bytes) requires encoding. You specify an encoding scheme (like 'utf-8').

text_to_encode = "résumé"
utf8_bytes = text_to_encode.encode('utf-8')
print(f"'{text_to_encode}' encoded to UTF-8: {utf8_bytes}")
# Output: 'résumé' encoded to UTF-8: b'r\xc3\xa9sum\xc3\xa9'

# Alternative using bytes() constructor
# utf8_bytes_alt = bytes(text_to_encode, 'utf-8')

Decoding (bytes to str)

Converting binary data (bytes) back to text (str) requires decoding using the same encoding scheme it was encoded with.

utf8_bytes = b'r\xc3\xa9sum\xc3\xa9'
decoded_text = utf8_bytes.decode('utf-8')
print(f"{utf8_bytes} decoded from UTF-8: '{decoded_text}'")
# Output: b'r\xc3\xa9sum\xc3\xa9' decoded from UTF-8: 'résumé'

# Alternative using str() constructor
# decoded_text_alt = str(utf8_bytes, 'utf-8')
note

Using the wrong encoding during decoding will result in errors (UnicodeDecodeError) or garbled text ("mojibake").

Conclusion

The NameError: name 'unicode' is not defined is a definitive sign of running Python 2 code, or code written with Python 2 idioms, in a Python 3 environment.

The primary solution is to replace all uses of the name unicode with the Python 3 equivalent, which is almost always str.

  • Replace unicode() calls used for decoding with .decode() or str(bytes, encoding).
  • Replace unicode() calls used for string conversion with str().
  • Replace isinstance(..., unicode) checks with isinstance(..., str).

Understanding the fundamental shift from Python 2's str/unicode model to Python 3's bytes/str model is key to correctly handling text and binary data and resolving this NameError. Avoid compatibility shims unless absolutely necessary for cross-version support.