AttributeError: 'str' object has no attribute 'X in Python

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
15 min

banner

# Table of Contents

  1. AttributeError: 'str' object has no attribute 'X'
  2. AttributeError: 'str' object has no attribute 'ITEMS' or 'KEYS'
  3. AttributeError: 'str' object has no attribute 'CONTAINS'
  4. AttributeError: 'str' object has no attribute 'WRITE'
  5. AttributeError: 'str' object has no attribute 'READ'
  6. AttributeError: 'str' object has no attribute 'REMOVE'

# AttributeError: 'str' object has no attribute 'X' in Python

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.

attributeerror str object has no-attribute

Here is an example of how the error occurs.

main.py
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.

# Calling the decode() method on a string causes the error

A common cause of the error is trying to call the decode() method on a string (already decoded) object.

main.py
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.

Another common cause of the error is misspelling a built-in method (method names are case-sensitive).

# Accessing a list at a specific index before calling a list method

Make sure you aren't accessing a list at a specific index before calling a list-method.

main.py
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.

main.py
my_list = ['bobby', 'hadz', '.'] my_list.append('com') print(my_list) # 👉️ ['bobby', 'hadz', '.', 'com']

# Reassigning the variable to a string

Make sure you aren't reassigning the variable to a string somewhere in your code.

main.py
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.

# Calling the write or read method on the filename

If you are writing to or reading from a file, make sure you aren't calling the write() or read() methods on the filename.

main.py
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.

main.py
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')

# Checking if a string contains a substring

If you need to check if a substring is in a string, use the in operator.

main.py
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.

main.py
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.

# Checking if an object contains an attribute

If you need to check whether an object contains an attribute, use the hasattr function.

main.py
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:

NameDescription
objectThe object we want to test for the existence of the attribute
nameThe 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.

Using the 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.

# Figure out where the variable got assigned a string

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.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

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:

  • you haven't misspelled a method or attribute that exists on the str object.
  • you haven't assigned a string to a variable that should store a different value.
  • you aren't trying to call decode() on a variable that already stores a string.

# Examples of solving the error for specific methods

Here are some examples of solving the error for specific methods. Click on the link to navigate to the subheading.

  1. AttributeError: 'str' object has no attribute 'items' or 'keys'
  2. AttributeError: 'str' object has no attribute 'contains'
  3. AttributeError: 'str' object has no attribute 'write'
  4. AttributeError: 'str' object has no attribute 'read'
  5. AttributeError: 'str' object has no attribute 'remove'
  6. AttributeError: 'str' object has no attribute 'append'
  7. AttributeError: 'str' object has no attribute 'decode'
  8. AttributeError: 'str' object has no attribute 'get' (Python)
  9. AttributeError: 'str' object has no attribute 'strftime'

# AttributeError: 'str' object has no attribute 'items' or 'keys'

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.

attributeerror str object has no attribute items

Here is an example of how the error occurs.

main.py
# 👇️ 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())

attributeerror str object has no attribute 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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

Since items() and keys() are not methods implemented by strings, the error is caused.

  1. AttributeError: 'str' object has no attribute 'contains'
  2. AttributeError: 'str' object has no attribute 'write'
  3. AttributeError: 'str' object has no attribute 'read'
  4. AttributeError: 'str' object has no attribute 'remove'
  5. AttributeError: 'str' object has no attribute 'append'
  6. AttributeError: 'str' object has no attribute 'decode'
  7. AttributeError: 'str' object has no attribute 'get' (Python)
  8. AttributeError: 'str' object has no attribute 'strftime'

# AttributeError: 'str' object has no attribute 'contains'

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.

attributeerror str object has no attribute contains

Here is an example of how the error occurs.

main.py
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.

main.py
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.

main.py
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.

main.py
my_str = 'bobbyhadz.com' print('bobby' in my_str) # 👉️ True print('another' in my_str) # 👉️ False

# Checking if a string contains a substring ignoring the case

If you need to check if a substring is contained in a string ignoring the case, convert both strings to lowercase.

main.py
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.

# Checking if a string does not contain a substring

If you need to check if a substring is NOT in a string, use the not in operator instead.

main.py
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.

When used with a dictionary, the operators check for the existence of the specified key in the dict object.

Note that empty strings are always considered to be a substring of any other string.

main.py
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.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

Since contains() is not a method implemented by strings, the error is caused.

  1. AttributeError: 'str' object has no attribute 'write'
  2. AttributeError: 'str' object has no attribute 'read'
  3. AttributeError: 'str' object has no attribute 'remove'
  4. AttributeError: 'str' object has no attribute 'append'
  5. AttributeError: 'str' object has no attribute 'decode'
  6. AttributeError: 'str' object has no attribute 'get' (Python)
  7. AttributeError: 'str' object has no attribute 'strftime'

# AttributeError: 'str' object has no attribute 'write'

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.

attributeerror str object has no attribute write

Here is an example of how the error occurs.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

Since the str object doesn't implement a write() method, the error is caused.

  1. AttributeError: 'str' object has no attribute 'read'
  2. AttributeError: 'str' object has no attribute 'remove'
  3. AttributeError: 'str' object has no attribute 'append'
  4. AttributeError: 'str' object has no attribute 'decode'
  5. AttributeError: 'str' object has no attribute 'get' (Python)
  6. AttributeError: 'str' object has no attribute 'strftime'

# AttributeError: 'str' object has no attribute 'read'

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.

attributeerror str object has no attribute read

Here is an example of how the error occurs.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

Since the str object doesn't implement a read() method, the error is caused.

  1. AttributeError: 'str' object has no attribute 'remove'
  2. AttributeError: 'str' object has no attribute 'append'
  3. AttributeError: 'str' object has no attribute 'decode'
  4. AttributeError: 'str' object has no attribute 'get' (Python)
  5. AttributeError: 'str' object has no attribute 'strftime'

# AttributeError: 'str' object has no attribute 'remove'

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.

attributeerror str object has no attribute remove

Here is an example of how the error occurs.

main.py
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.

main.py
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.

main.py
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.

main.py
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:

NameDescription
oldThe substring we want to replace in the string
newThe replacement for each occurrence of old
countOnly the first count occurrences are replaced (optional)
Note that the method doesn't change the original string. Strings are immutable in Python.

Here is an example of what printing the attributes of a string looks like.

main.py
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.

If you try to access any attribute that is not in this list, you will get the "AttributeError: str object has no attribute error".

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:

  1. AttributeError: 'str' object has no attribute 'append'
  2. AttributeError: 'str' object has no attribute 'decode'
  3. AttributeError: 'str' object has no attribute 'get'
  4. AttributeError: 'str' object has no attribute 'strftime'
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.