Python ValueError: substring not found
Why does this happen?
ValueError: substring not found when the
index() function fails to find a given substring.
Let's look at an example case. The code below runs a for loop over a word list, trying to locate each word inside the given quote:
The for loop fails at its third run because
index() cannot find
When we use
index() to locate substrings in whose existence we are not confident, we risk termination. We should reinforce our code against the error or replace the
index() call completely.
This article will discuss several solutions and their possible advantages over one another.
Solution 1: find()
On String values, the function
find() works almost identically to
index() with one crucial difference - when
find() fails, instead of raising an error, it returns
Let's bring back the example from the intro and swap the
find() also takes the optional
end parameters. So if we wanted to narrow the search between two indexes, we could still do it.
Below, the second
find() call uses the index where the first
'word' ends and the quote's length to bracket the search:
find() seems like the perfect substitute for
index(), there is a subtle difference: while
index() is available for lists and tuples,
find() only applies to string values.
It's also important to note that
-1 is a valid index marking the last element of a sequence. This can cause problems when using the fetched indexes in further processing.
You can see a simple demonstration of the pitfall below:
This issue, however, can easily be resolved by a conditional statement:
Solution 2: try-except
One way of working around a possible
ValueError is wrapping the
index() call in a
try-except block, like so:
This option takes a bit more typing but allows us to assign a fallback index or print a custom message when
Solution 3: if...in
One other solution is to ensure the existence of the substring using
if...in before calling
index(), like so:
One advantage this method has over the
try-except option is that we can compress the
if-else block into one line like this:
The downside is that
if...in impacts performance when used over many iterations due to the extra lookup to check if the substring exists. Refer to the previous solution if this performance hit is a concern.
index() function fails to find a given substring within a string, it raises the
ValueError: substring not found.
To prevent the program from crashing, we can replace the
index() method with
find(), which performs the same string operation yet fails in silence. It is also helpful to wrap the
index() call in a try-except block or to use
if-in to check the existence of the substring before calling