Last updated: Apr 8, 2024
Reading time·15 min
The Python "AttributeError: 'str' object has no attribute" occurs when we try to access an attribute that doesn't exist on string objects.
To solve the error, make sure the value is of the expected type before accessing the attribute.
Here is an example of how the error occurs.
my_str = 'bobbyhadz.com' # ⛔️ AttributeError: 'str' object has no attribute 'my_attribute' print(my_str.my_attribute)
We tried to access an attribute that doesn't exist on string objects and got the error.
If you print() the value you are accessing the attribute on, it will be a string.
To solve the error, track down where exactly you are setting the value to a string in your code and correct the assignment.
decode()
method on a string causes the errorA common cause of the error is trying to
call the decode()
method on a string
(already decoded) object.
my_str = 'bobbyhadz.com' # ⛔️ AttributeError: 'str' object has no attribute decoded = my_str.decode(enoding='utf-8')
To solve the error, remove the call to the decode()
method because if you have
a string, it is already decoded.
The decode()
method is used to decode a bytes
object into a string.
Make sure you aren't accessing a list at a specific index before calling a list-method.
my_list = ['bobby', 'hadz', '.'] # ⛔️ AttributeError: 'str' object has no attribute my_list[2].append('com')
We accessed the list element at index 2
, which is a string and called the
append()
method on the string which caused the error.
To solve the error, we have to call the append()
method on the list.
my_list = ['bobby', 'hadz', '.'] my_list.append('com') print(my_list) # 👉️ ['bobby', 'hadz', '.', 'com']
Make sure you aren't reassigning the variable to a string somewhere in your code.
my_list = ['bobby', 'hadz', '.'] # 👇️ The list got reassigned to a string my_list = 'hello world' # ⛔️ AttributeError: 'str' object has no attribute my_list.append('com')
We set the value of the my_list
variable to a list initially, but we set it to
a string later on which caused the error.
write
or read
method on the filenameIf you are writing to or reading from a file, make sure you aren't calling the
write()
or read()
methods on the filename.
file_name = 'example.txt' with open(file_name, 'w', encoding='utf-8') as my_file: # ⛔️ AttributeError: 'str' object has no attribute file_name.write('first line' + '\n') file_name.write('second line' + '\n') file_name.write('third line' + '\n')
The issue in the code sample is that we are calling the write()
method on a
string (the filename) whereas we should be calling it on the file object.
file_name = 'example.txt' with open(file_name, 'w', encoding='utf-8') as my_file: my_file.write('first line' + '\n') my_file.write('second line' + '\n') my_file.write('third line' + '\n')
If you need to check if a substring is in a string, use the in
operator.
my_string = 'bobbyhadz.com' if '.com' in my_string: # 👇️ This runs print('string contains substring') else: print('string does NOT contain substring')
The in
operator returns True
if the substring is contained in the string and
False
otherwise.
If you need to check if a string contains a substring in a case-insensitive manner, convert both strings to lowercase.
my_string = 'BOBBYHADZ.COM' substring = '.com' if substring.lower() in my_string.lower(): # 👇️ This runs print('string contains substring') else: print('string does NOT contain substring')
Converting both strings to the same case allows for a case-insensitive membership test.
If you need to check whether an object contains an attribute, use the hasattr
function.
my_string = 'bobbyhadz.com' if hasattr(my_string, 'upper'): print(my_string.upper()) # 👉️ BOBBYHADZ.COM else: print('Attribute is not present in object')
The hasattr() function takes the following 2 parameters:
Name | Description |
---|---|
object | The object we want to test for the existence of the attribute |
name | The name of the attribute to check for in the object |
The hasattr()
function returns True
if the string is the name of one of the
object's attributes, otherwise False
is returned.
hasattr
function would handle the error if the attribute doesn't exist on the object, however, you still have to figure out where the variable gets assigned a string in your code.A good way to start debugging is to print(dir(your_object))
and see what
attributes a string has.
Here is an example of what printing the attributes of a string
looks like.
my_string = 'hello world' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
To solve the error, either convert the value to the correct type before accessing the attribute or correct the type of value you are assigning to the variable before accessing any attributes.
Make sure:
str
object.decode()
on a variable that already stores a
string.Here are some examples of solving the error for specific methods. Click on the link to navigate to the subheading.
The Python AttributeError: 'str' object has no attribute 'items' or 'keys'
occurs when we try to call the items()
or keys()
method on a string instead
of a dictionary.
To solve the error, make sure to parse the string if you have a JSON string or
correct the assignment and call items()
or keys()
on a dict.
Here is an example of how the error occurs.
# 👇️ this is a string my_dict = '{"name": "Bobby Hadz", "age": 30}' # ⛔️ AttributeError: 'str' object has no attribute 'items' print(my_dict.items()) # ⛔️ AttributeError: 'str' object has no attribute 'keys' print(my_dict.keys())
We tried to call the items()
and keys()
methods on a string and got the
error.
If you have a JSON string, use the json.loads()
method to parse it into a
native Python dictionary.
import json my_dict = '{"name": "Bobby Hadz", "age": 30}' # 👇️ Parse the JSON string to a native Python dict parsed = json.loads(my_dict) # 👇️ dict_items([('name', 'Bobby Hadz'), ('age', 30)]) print(parsed.items()) # 👇️ dict_keys(['name', 'age']) print(parsed.keys())
We used the json.loads()
method to parse the JSON string into a Python
dictionary before calling the items()
and keys()
methods.
If you need to check if the value is a dictionary before calling the items()
or keys()
method, use the isinstance
function.
my_dict = {"name": "Bobby Hadz", "age": 30} if isinstance(my_dict, dict): # 👇️ dict_items([('name', 'Bobby Hadz'), ('age', 30)]) print(my_dict.items())
The isinstance function returns
True
if the passed-in object is an instance or a subclass of the passed-in
class.
If you are making an HTTP request, make sure you aren't converting the headers
dictionary to JSON.
import requests def make_request(): res = requests.post( 'https://reqres.in/api/users', data={'name': 'Bobby Hadz', 'job': 'programmer'}, # 👇️ Should be a Python dictionary (NOT json str) headers={'Accept': 'application/json', 'Content-Type': 'application/json'} ) print(res.json()) # parse JSON response to native Python object make_request()
The headers
keyword argument should be a Python dictionary, not a JSON string.
Make sure you aren't calling the json.dumps()
method on your dictionary as
that would convert it to a JSON string.
import json my_dict = {"name": "Bobby Hadz", "age": 30} print(type(my_dict)) # 👉️ <class 'dict'> # 👇️ json.dumps() converts a Python object to JSON string json_str = json.dumps(my_dict) print(type(json_str)) # 👉️ <class 'str'>
The json.dumps method converts a Python object to a JSON formatted string.
If you have a JSON string and are trying to parse it into a native Python
dictionary, use the json.loads()
method.
import json json_str = r'{"name": "Bobby Hadz", "age": 30}' my_dict = json.loads(json_str) print(type(my_dict)) # 👉️ <class 'dict'>
The json.loads method parses a JSON string into a native Python object.
If the data being parsed is not a valid JSON string, a JSONDecodeError
is
raised.
A good way to start debugging is to print(dir(your_object))
and see what
attributes a string has.
Here is an example of what printing the attributes of a string
looks like.
my_string = 'bobbyhadz.com' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
Since items()
and keys()
are not methods implemented by strings, the error
is caused.
The Python "AttributeError: 'str' object has no attribute 'contains'" occurs
when we try to call the contains()
method on a string.
To solve the error, use the in
operator, e.g. 'ab' in 'abc'
as strings
don't have a contains
method.
Here is an example of how the error occurs.
my_str = 'bobbyhadz.com' # ⛔️ AttributeError: 'str' object has no attribute 'contains' print(my_str.contains('com'))
We tried to call the contains()
method on a string and got the error because
strings don't have a contains
method.
You can use the in
operator to check if a substring is contained in a string.
my_str = 'bobbyhadz.com' if 'com' in my_str: print('substring is contained in string') # 👉️ this runs else: print('substring is NOT contained in string')
You can also extract the logic into a reusable function.
def contains(string, substring): return substring in string print(contains('bobbyhadz.com', 'com')) # 👉️ True print(contains('bobbyhadz.com', 'abc')) # 👉️ False
The in operator tests
for membership. For example, x in s
evaluates to True
if x
is a member of
s
, otherwise it evaluates to False
.
my_str = 'bobbyhadz.com' print('bobby' in my_str) # 👉️ True print('another' in my_str) # 👉️ False
If you need to check if a substring is contained in a string ignoring the case, convert both strings to lowercase.
my_str = 'BOBBYHADZ.COM' my_substr = 'com' if my_substr.lower() in my_str.lower(): print('substring is in string') # 👉️ This runs else: print('substring is not in string')
We converted both of the strings to lowercase to be able to check if a substring is in a string ignoring the case.
If you need to check if a substring is NOT in a string, use the not in
operator instead.
my_str = 'BOBBYHADZ.COM' if 'another' not in my_str: print('substring is NOT in string') # 👉️ This runs
x
not in s
returns the negation of x
in s
.
All built-in sequences and set types support the in
and not in
operators.
dict
object.Note that empty strings are always considered to be a substring of any other string.
my_str = 'bobbyhadz.com' print('' in my_str) # 👉️ True
A good way to start debugging is to print(dir(your_object))
and see what
attributes a string has.
Here is an example of what printing the attributes of a string
looks like.
my_string = 'bobbyhadz.com' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
Since contains()
is not a method implemented by strings, the error is caused.
The Python "AttributeError: 'str' object has no attribute 'write'" occurs when
we call the write()
method on a string (e.g. the filename) instead of a file
object.
To solve the error, call the write()
method on the file object after opening
the file.
Here is an example of how the error occurs.
file_name = 'example.txt' with open(file_name, 'w', encoding='utf-8') as my_file: # ⛔️ AttributeError: 'str' object has no attribute 'write' file_name.write('first line' + '\n') file_name.write('second line' + '\n') file_name.write('third line' + '\n')
The issue is that we called the write()
method on the filename, which is a
string.
Instead, call the write()
method on the file object after you open it.
file_name = 'example.txt' with open(file_name, 'w', encoding='utf-8') as my_file: # ✅ Calling write() on file object my_file.write('first line' + '\n') my_file.write('second line' + '\n') my_file.write('third line' + '\n')
The with open() syntax takes care of automatically closing the file even if an exception is thrown.
Alternatively, you can store the file object into a variable and manually close it.
file_name = 'example.txt' my_file = open(file_name, 'w', encoding='utf-8') my_file.write('first line' + '\n') my_file.write('second line' + '\n') my_file.write('third line' + '\n') my_file.close()
Note that it's better to use the with open()
syntax as it automatically closes
the file after we are done.
If you need to append data to a file, use the a
flag instead of w
.
file_name = 'example.txt' with open(file_name, 'a', encoding='utf-8') as my_file: my_file.write('first line' + '\n') my_file.write('second line' + '\n') my_file.write('third line' + '\n')
If you need to read from the file and write to the file, use the r+
flag.
file_name = 'example.txt' with open(file_name, 'r+', encoding='utf-8') as my_file: read_data = my_file.read() print(read_data) my_file.write('first line' + '\n') my_file.write('second line' + '\n') my_file.write('third line' + '\n')
A good way to start debugging is to print(dir(your_object))
and see what
attributes a string has.
Here is an example of what printing the attributes of a string
looks like.
my_string = 'hello world' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
Since the str
object doesn't implement a write()
method, the error is
caused.
The Python "AttributeError: 'str' object has no attribute 'read'" occurs when
we call the read()
method on a string (e.g. a filename) instead of a file
object or use the json.load()
method by mistake.
To solve the error, call the read()
method on the file object after opening
the file.
Here is an example of how the error occurs.
file_name = 'example.txt' with open(file_name, encoding='utf-8') as f: # ⛔️ AttributeError: 'str' object has no attribute 'read' read_data = file_name.read() print(read_data)
We tried to call the read()
method on the filename string instead of the file
object which caused the error.
If you are reading from a file, make sure to call the read()
method on the
file object instead.
file_name = 'example.txt' with open(file_name, encoding='utf-8') as f: # ✅ calling read() on file object read_data = f.read() print(read_data)
Another common cause of the error is using the json.load()
method when trying
to parse a JSON string into a native Python object.
import json # ⛔️ AttributeError: 'str' object has no attribute 'read' result = json.load('{"name": "Alice"}')
The json.load method is used to deserialize a file to a Python object, whereas the json.loads method is used to deserialize a JSON string to a Python object.
If you are trying to parse a JSON string into a native Python object, use the
json.loads
(with s
) method instead.
import json result = json.loads('{"name": "Alice"}') print(type(result)) # 👉️ <class 'dict'> print(result) # 👉️ {'name': 'Alice'}
We parsed the JSON string into a dictionary using the json.loads()
method.
If you are trying to use the json.load()
method to deserialize a file to a
Python object, open the file and pass the file object to the json.load()
method.
import json file_name = 'example.json' with open(file_name, 'r', encoding='utf-8') as f: my_data = json.load(f) print(my_data) # 👉️ {'name': 'Alice', 'age': 30}
The json.load()
method expects a text file or a binary file containing a JSON
document that implements a .read()
method. If you call the json.load()
method with a string, it tries to call the read()
method on the string.
If you are getting the error when using the urllib
module, open the request
before calling the read()
method.
import urllib.request with urllib.request.urlopen('http://www.python.org/') as f: # 👇️ call read() here print(f.read())
A good way to start debugging is to print(dir(your_object))
and see what
attributes a string has.
Here is an example of what printing the attributes of a string
looks like.
my_string = 'hello world' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
Since the str
object doesn't implement a read()
method, the error is caused.
The Python "AttributeError: 'str' object has no attribute 'remove'" occurs
when we try to call the remove()
method on a string instead of a list.
To solve the error, call the remove()
method on a list or use the
replace()
method if trying to remove characters from a string.
Here is an example of how the error occurs.
my_list = ['a', 'b', 'c'] # ⛔️ AttributeError: 'str' object has no attribute 'remove' my_list[0].remove('a')
We accessed the list element at index 0
(a string) and called the remove()
method on the string which caused the error.
If you need to remove an item from a list, call the remove()
method on the
list.
my_list = ['a', 'b', 'c'] my_list.remove('a') print(my_list) # 👉️ ['b', 'c']
The list.remove() method removes the first item from the list whose value is equal to the passed-in argument.
The method raises a ValueError
if there is no such item.
If you need to handle a scenario where the item is not found in the list, use a try/except statement.
my_list = ['a', 'b', 'c'] try: my_list.remove('r') except ValueError: print('Item not in list') print(my_list) # 👉️ ['a', 'b', 'c']
The remove()
method mutates the original list and
returns None.
If you are trying to remove characters from a string, use the replace()
method
instead.
my_str = 'apple banana kiwi' new_str = my_str.replace('banana', '') print(new_str) # 👉️ "apple kiwi"
By replacing a substring with an empty string, we effectively remove the substring from the string.
The str.replace() method returns a copy of the string with all occurrences of a substring replaced by the provided replacement.
The method takes the following parameters:
Name | Description |
---|---|
old | The substring we want to replace in the string |
new | The replacement for each occurrence of old |
count | Only the first count occurrences are replaced (optional) |
Here is an example of what printing the attributes of a string
looks like.
my_string = 'hello world' # [ 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', # 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', # 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', # 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', # 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', # 'title', 'translate', 'upper', 'zfill'] print(dir(my_string))
If you pass a class to the dir() function, it returns a list of names of the class's attributes, and recursively of the attributes of its bases.
Since the str
object doesn't implement a remove()
method, the error is
caused.
If you got any of the following errors, click on the relevant to you article: