TypeError: expected string or bytes-like object in Python

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
4 min

banner

# TypeError: expected string or bytes-like object in Python

The Python "TypeError: expected string or bytes-like object" occurs when you pass a non-string argument to a function that expects a string.

To solve the error, make sure to call the function with a string argument instead.

typeerror expected string or bytes like object

Here is an example of how the error occurs.

main.py
import re my_int = 100 # โ›”๏ธ TypeError: expected string or bytes-like object result = re.sub(r'[0-9]', '_', my_int) # ๐Ÿ‘ˆ๏ธ Third arg must be str

We passed an integer as the third argument to the re.sub method, but the method expects a string argument.

The re.sub() method takes 3 arguments:

  1. A pattern to match in a string.
  2. The replacement string for the matches.
  3. The string in which to match the pattern.

# Convert the value to a string to solve the error

One way to solve the error is to use the str() class to convert the value to a string.

main.py
import re my_int = 100 # โœ… convert to str result = re.sub(r'[0-9]', '_', str(my_int)) print(result) # ๐Ÿ‘‰๏ธ '___'

convert value to string to solve the error

We used the str() class to convert the integer to a string when calling re.sub().

You might also be iterating over a sequence and calling the re.sub() method with each item.

If you aren't sure whether all of the items in the sequence are strings, pass each to the str() class.
main.py
import re my_list = [0, 10, 100] new_list = [] for item in my_list: result = re.sub(r'[0-9]', '_', str(item)) print(result) new_list.append(result) print(new_list) # ๐Ÿ‘‰๏ธ ['_', '__', '___']

pass each value to str class

We used a for loop to iterate over the list.

On each iteration, we pass the current item to the str() class before using re.sub().

# Providing a fallback value for None values

If your sequence stores None values, provide an empty string as a fallback.

main.py
import re my_value = None result = re.sub(r'[0-9]', '_', my_value or '') print(repr(result)) # ๐Ÿ‘‰๏ธ ''

provide fallback value for none values

The expression None or '' evaluates to an empty string which helps us avoid the error.

The re.sub() method returns a new string that is obtained by replacing the occurrences of the pattern with the provided replacement.

Here is an example of how to solve the error when working with lists.

main.py
import re from ast import literal_eval my_list = [5, 'a', 0, 'b', 1, 'c', 2, 6] # โœ… remove letters from a list my_str = re.sub(r'[a-zA-Z]+', '', str(my_list)) print(my_str) # ๐Ÿ‘‰๏ธ [5, '', 0, '', 1, '', 2, 6] # โœ… remove empty strings from a string new_str = my_str.replace("''", '') print(new_str) # ๐Ÿ‘‰๏ธ [5, , 0, , 1, , 2, 6] # โœ… remove double commas from a string new_str = new_str.replace(", ,", ',') print(new_str) # ๐Ÿ‘‰๏ธ [5, 0, 1, 2, 6] # โœ… convert the string representation of list to list my_list = literal_eval(new_str) print(my_list) # ๐Ÿ‘‰๏ธ [5, 0, 1, 2, 6] print(type(my_list)) # ๐Ÿ‘‰๏ธ <class 'list'>
  1. We first remove all letters from the list, converting the list to a string.
  2. Then we remove all empty strings from the string and replace double commas with a single comma.
  3. The last step is to use the literal_eval() method to convert the string to a list.

You might also get the error when using the re.findall() method.

# Encountering the error when using re.findall()

Here is an example of how the error occurs when using re.findall().

main.py
import re my_int = 100 # โ›”๏ธ TypeError: expected string or bytes-like object, got 'int' result = re.findall(r'[0-9]', my_int)

To solve the error, convert the second argument in the call to findall() to a string.

main.py
import re my_int = 100 result = re.findall(r'[0-9]', str(my_int)) print(result) # ๐Ÿ‘‰๏ธ ['1', '0', '0']

We used the str() class to convert a value to a string before calling re.findall().

Here is another example of how the error occurs when using the re.findall() method.

main.py
import re with open('example.txt', 'r', encoding='utf-8') as f: lines = f.readlines() # ๐Ÿ‘ˆ๏ธ this is a list # โ›”๏ธ TypeError: expected string or bytes-like object m = re.findall(r'\w+th', lines) # ๐Ÿ‘ˆ๏ธ passing list instead of str

We passed a list to the re.findall method, but the method takes a string argument.

To solve the error, call the read() method on the file object to get a string of the file's contents and pass the string to the findall method.

main.py
import re with open('example.txt', 'r', encoding='utf-8') as f: my_str = f.read() print(type(my_str)) # ๐Ÿ‘‰๏ธ <class 'str'> m = re.findall(r'\w+th', my_str) print(m) # ๐Ÿ‘‰๏ธ ['fourth', 'fifth']

The example assumes that you have a file named example.txt with the following contents:

example.txt
first second third fourth fifth

All we had to do was make sure we passed a string as the second argument to the re.findall method.

The re.findall method takes a pattern and a string as arguments and returns a list of strings containing all non-overlapping matches of the pattern in the string.

# Solve the error when reading from a JSON file

If you got the error while trying to read a JSON file, use 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) # โœ… call json.load() with file obj print(my_data) # ๐Ÿ‘‰๏ธ {'name': 'Alice', 'age': 30} print(my_data['name']) # ๐Ÿ‘‰๏ธ 'Alice' print(type(my_data)) # ๐Ÿ‘‰๏ธ <class 'dict'>

The code sample above assumes that you have an example.json file in the same directory.

example.json
{"name": "Alice", "age": 30}

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.

The json.load() method expects a text file or a binary file containing a JSON document that implements a .read() method.

If the error persists, use your IDE to check the type of the method's parameters.

One of the arguments the method takes must be of type str and you are passing a value of a different type.

# Checking what type a variable stores

If you aren't sure what type of object a variable stores, use the built-in type() class.

main.py
my_str = 'hello' print(type(my_str)) # ๐Ÿ‘‰๏ธ <class 'str'> print(isinstance(my_str, str)) # ๐Ÿ‘‰๏ธ True my_dict = {'name': 'Alice', 'age': 30} print(type(my_dict)) # ๐Ÿ‘‰๏ธ <class 'dict'> print(isinstance(my_dict, dict)) # ๐Ÿ‘‰๏ธ True

The type class returns the type of an object.

The isinstance() function returns True if the passed-in object is an instance or a subclass of the passed-in class.

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.

Copyright ยฉ 2024 Borislav Hadzhiev