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 usingu'...'
literals or theunicode()
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'sunicode
). This is the standard type for all text.u'...'
literals are no longer needed or used.bytes
: Represents sequences of bytes (binary data). Created usingb'...'
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)
Solution 1: Replace unicode()
with str()
(Recommended)
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 withstr(byte_string, encoding)
or, more commonly,byte_string.decode(encoding)
. - If the original code used
unicode(object)
to get a text representation, replace it withstr(object)
. - If the original code used
isinstance(obj, unicode)
to check for text, replace it withisinstance(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
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'>)
- 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 withb'...'
orb"..."
. 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')
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()
orstr(bytes, encoding)
. - Replace
unicode()
calls used for string conversion withstr()
. - Replace
isinstance(..., unicode)
checks withisinstance(..., 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.