Python Forum
ValueError: substring not found
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ValueError: substring not found
#1
Let me first start this off by stating that I am a complete beginner to coding and my attempts to fix this have been limited. I am trying to follow this Arduino controlled piano robot. It takes a textified midi file and uses python to translate it into 8-bit.
output_file = open("translated.txt", "w")
input_file = open("C:\\Users\\nby20\\Downloads\\megalovania.txt")
raw_input_data = input_file.read()
work_data = raw_input_data.splitlines()
result = []

#output_file = open("result.txt", "w")

def main():

    for a in work_data:
        temp_time = time_finder(a)
        
        
        if result == []:
            result.append(str(temp_time) + ",")
            if on_off_finder(a):
                result[-1] += set_bit(True, note_finder(a))
            elif not on_off_finder(a):
                result[-1] += set_bit(True, note_finder(a))
                
        elif time_finder_comm(result[-1]) == temp_time:
            result[-1] = str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1)

        elif time_finder_comm(result[-1]) != temp_time:
            result.append(str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1))

    for b in result:
        output_file.write(b)
        output_file.write("\n")

    output_file.close()
            
def set_bit(On, note):
    #Takes boolean for if it is on or not, and note number.
    #Generates bit
    if(note >= 21 and note <= 28 and On):
        return str(2**(note - 21)) + ",0,0,0,0,0,0,0,0,0,0"
    elif(note >= 29 and note <= 36 and On):
        return "0," + str(2**(note - 29)) + ",0,0,0,0,0,0,0,0,0"
    elif(note >= 37 and note <= 44 and On):
        return "0,0," + str(2**(note - 37)) + ",0,0,0,0,0,0,0,0"
    elif(note >= 45 and note <= 52 and On):
        return "0,0,0," + str(2**(note - 45)) + ",0,0,0,0,0,0,0"
    elif(note >= 53 and note <= 60 and On):
        return "0,0,0,0," + str(2**(note - 53)) + ",0,0,0,0,0,0"
    elif(note >= 61 and note <= 68 and On):
        return "0,0,0,0,0," + str(2**(note - 61)) + ",0,0,0,0,0"
    elif(note >= 69 and note <= 76 and On):
        return "0,0,0,0,0,0," + str(2**(note - 69)) + ",0,0,0,0"
    elif(note >= 77 and note <= 84 and On):
        return "0,0,0,0,0,0,0," + str(2**(note - 77)) + ",0,0,0"
    elif(note >= 85 and note <= 92 and On):
        return "0,0,0,0,0,0,0,0," + str(2**(note - 85)) + ",0,0"
    elif(note >= 93 and note <= 100 and On):
        return "0,0,0,0,0,0,0,0,0," + str(2**(note - 93)) + ",0"
    elif(note >= 101 and note <= 108 and On):
        return "0,0,0,0,0,0,0,0,0,0," + str(2**(note - 101))
    else:
        return "0,0,0,0,0,0,0,0,0,0,0"

def set_bit_prev(On, note, index):
    #Same as set_bit but previous aware
    temp = result[index]
    temp = temp[(temp.find(",") + 1):]
    
    if(note >= 21 and note <= 28):
        local_temp = temp[0:temp.find(",")]
        if(On):
            return str(int(local_temp) + (2**(note - 21))) + temp[temp.find(","):]
        if(not On):
            return str(int(local_temp) - (2**(note - 21))) + temp[temp.find(","):]
        
    elif(note >= 29 and note <= 36):
        local_temp = temp[(temp.find(",") + 1):indexTh(temp, ",", 2)]
        if(On):
            return temp[0:temp.find(",") + 1] + str(int(local_temp) + (2**(note - 29))) + temp[indexTh(temp, ",", 2):]
        if(not On):
            return temp[0:temp.find(",") + 1] + str(int(local_temp) - (2**(note - 29))) + temp[indexTh(temp, ",", 2):]
        
    elif(note >= 37 and note <= 44):
        local_temp = temp[(indexTh(temp, ",", 2) + 1):indexTh(temp, ",", 3)]
        if(On):
            return temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) + (2**(note - 37))) + temp[indexTh(temp, ",", 3):]
        if(not On):
            return temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) - (2**(note - 37))) + temp[indexTh(temp, ",", 3):]
        
    elif(note >= 45 and note <= 52):
        local_temp = temp[(indexTh(temp, ",", 3) + 1):indexTh(temp, ",", 4)]
        if(On):
            return temp[0:indexTh(temp, ",", 3) + 1] + str(int(local_temp) + (2**(note - 45))) + temp[indexTh(temp, ",", 4):]
        if(not On):
            return temp[0:indexTh(temp, ",", 3) + 1] + str(int(local_temp) - (2**(note - 45))) + temp[indexTh(temp, ",", 4):]
        
    elif(note >= 53 and note <= 60):
        local_temp = temp[(indexTh(temp, ",", 4) + 1):indexTh(temp, ",", 5)]
        if(On):
            return temp[0:indexTh(temp, ",", 4) + 1] + str(int(local_temp) + (2**(note - 53))) + temp[indexTh(temp, ",", 5):]
        if(not On):
            return temp[0:indexTh(temp, ",", 4) + 1] + str(int(local_temp) - (2**(note - 53))) + temp[indexTh(temp, ",", 5):]
        
    elif(note >= 61 and note <= 68):
        local_temp = temp[(indexTh(temp, ",", 5) + 1):indexTh(temp, ",", 6)]
        if(On):
            return temp[0:indexTh(temp, ",", 5) + 1] + str(int(local_temp) + (2**(note - 61))) + temp[indexTh(temp, ",", 6):]
        if(not On):
            return temp[0:indexTh(temp, ",", 5) + 1] + str(int(local_temp) - (2**(note - 61))) + temp[indexTh(temp, ",", 6):]
        
    elif(note >= 69 and note <= 76):
        local_temp = temp[(indexTh(temp, ",", 6) + 1):indexTh(temp, ",", 7)]
        if(On):
            return temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) + (2**(note - 69))) + temp[indexTh(temp, ",", 7):]
        if(not On):
            return temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) - (2**(note - 69))) + temp[indexTh(temp, ",", 7):]
        
    elif(note >= 77 and note <= 84):
        local_temp = temp[(indexTh(temp, ",", 7) + 1):indexTh(temp, ",", 8)]
        if(On):
            return temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) + (2**(note - 77))) + temp[indexTh(temp, ",", 8):]
        if(not On):
            return temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) - (2**(note - 77))) + temp[indexTh(temp, ",", 8):]
        
    elif(note >= 85 and note <= 92):#error here
        local_temp = temp[(indexTh(temp, ",", 8) + 1):indexTh(temp, ",", 9)]
        if(On):
            return temp[0:indexTh(temp, ",", 8) + 1] + str(int(local_temp) + (2**(note - 85))) + temp[indexTh(temp, ",", 9):]
        if(not On):
            return temp[0:indexTh(temp, ",", 8) + 1] + str(int(local_temp) - (2**(note - 85))) + temp[indexTh(temp, ",", 9):]
        
    elif(note >= 93 and note <= 100):
        local_temp = temp[(indexTh(temp, ",", 9) + 1):indexTh(temp, ",", 10)]
        if(On):
            return temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) + (2**(note - 93))) + temp[indexTh(temp, ",", 10):]
        if(not On):
            return temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) - (2**(note - 93))) + temp[indexTh(temp, ",", 10):]
        
    elif(note >= 101 and note <= 108):
        local_temp = temp[(indexTh(temp, ",", 10) + 1):]
        if(On):
            return temp[0:indexTh(temp, ",", 10) + 1] + str(int(local_temp) + (2**(note - 101)))
        if(not On):
            return temp[0:indexTh(temp, ",", 10) + 1] + str(int(local_temp) - (2**(note - 101)))
        

def indexTh(in_string, find_this, th):
    #Takes String, string to find, and order to find string to find at that order
    #returns index
    order = 1
    last_index = 0
    while(True):
        temp = in_string.find(find_this, last_index)
        if(temp == -1):
            return -1
        if(order == th):
            return temp
        order += 1
        last_index = temp + 1

def time_finder(in_string):
    #Takes a string and finds time, returns it as an int
    time_end = in_string.index(" ")
    return int(in_string[0:time_end])

def time_finder_comm(in_string):
    #Takes a string and finds time, returns it as an int comma
    time_end = in_string.index(",")
    return int(in_string[0:time_end])
    
def note_finder(in_string):
    #Takes a string, looks for n=, returns n value as an int
    num_start = in_string.index("n=") + 2
    num_end = in_string.index("v=") - 1
    return int(in_string[num_start:num_end])

def on_off_finder(in_string):
    #takes a string, looks for On or Off, return true if On
    start = in_string.index(" ") + 1
    end = in_string.index("ch=") - 1
    if in_string[start:end] == "On":
        return True
    elif in_string[start:end] == "Off":
        return False

main()
This link to the textified midi file was used. before running the code I changed the input_file = open to text file path like so,

input_file = open("C:\\Users\\nby20\\Downloads\\megalovania.txt")
I am not sure if this is correct but I think it works.
After running the code I get a text output file as expected however it is blank and I get a few errors:

Traceback (most recent call last):
File "C:\Users\nby20\Downloads\python_code_for_translation.py", line 184, in <module>
   main()
File "C:\Users\nby20\Downloads\python_code_for_translation.py", line 23, in main
   result[-1] = str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1)
File "C:\Users\nby20\Downloads\python_code_for_translation.py", line 178, in on_off_finder
   end = in_string.index("ch=") - 1 
ValueError: substring not found
I found that anything except for the lines containing actual data for the notes was not readable by the code and I deleted those portions and ended up with this updated file.
After running that updated file through the code I got a similar erorr
Traceback (most recent call last):
  File "C:\Users\nby20\Downloads\python_code_for_translation (1).py", line 184, in <module>
    main()
  File "C:\Users\nby20\Downloads\python_code_for_translation (1).py", line 12, in main
    temp_time = time_finder(a)
  File "C:\Users\nby20\Downloads\python_code_for_translation (1).py", line 161, in time_finder
    time_end = in_string.index(" ")
ValueError: substring not found
Any suggestions on how to fix this would be greatly appreciated.
Reply
#2
string.index raises a ValueError exception when the substring is not found. You can look for another function that returns a status instead of throwing an exception, but you should start getting used to using exceptions because they are used a lot in Python.

def on_off_finder(in_string):
    #takes a string, looks for On or Off, return true if On
    try:
        start = in_string.index(" ") + 1
        end = in_string.index("ch=") - 1
        if in_string[start:end] == "On":
            return True
        elif in_string[start:end] == "Off":
            return False
    except ValueError:
        pass  # Optionally do something else here
    return False
I'm not exactly sure what this function is supposed to do other that what the comment describe. As it was written it looks like ever in_string is expected to contain "On" or "Off" and that this key will follow the first space and is immediately followed by "ch=". That is really restrictive syntax. Your code will throw a ValueError exception if the string doesn't include a space, or if it doesn't include "ch=" (exactly, including case).

Your program will work better if you don't assume every string has to follow a particular pattern. I would write your function to try to process the string, determine if it is valid, if valid return the result, and if invalid print a message. Look a the invalid strings to help you determine if your parser is wrong or if the file contains strings with a different pattern that you can ignore or process differently

Python has really good tools for parsing strings. I think you might find regex interesting
Reply
#3
When you use string_object.index(substring), it looks for the occurrence of substring in the string_object. If substring is present, the method returns the index at which the substring is present, otherwise, it throws ValueError: substring not found.

Using Python’s “in” operator

The simplest and fastest way to check whether a string contains a substring or not in Python is the “in” operator . This operator returns true if the string contains the characters, otherwise, it returns false .

Quote:str="Hello, World!"
print("World" in str)//output is True

Python “in” operator takes two arguments, one on the left and one on the right, and returns True if the left argument string is contained within the right argument string. It is important to note that the “in” operator is case sensitive i.e, it will treat the Uppercase characters and Lowercase characters differently.
Reply
#4
Regex could be a solution:
import re


def on_off_finder(in_string):
    values = ("off", "on")
    # index   [ 0 ]  [ 1]
    # bool(0) -> False
    # bool(1) -> True
    if match := re.search(r"ch=(on|off)", in_string.lower()):
        # it does only match, if ch=on or ch=off was
        # in_string.lower()
        # then getting the group1, which is in parentheses
        # then searching the index for off/on
        # converting the index (0 or 1) into bool
        # return this value
        return bool(values.index(match.group(1)))
    else:
        # ch=on or ch=off was not in_string.lower()
        return False
To check the regex, visit: https://regex101.com/
Don't forget to select on the left side Python

Joke: If you have a problem and want to solve it with regex, then you have two problems.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
(Aug-08-2022, 10:05 AM)DeaD_EyE Wrote: Joke: If you have a problem and want to solve it with regex, then you have two problems

Not that I want to add noise to this thread: I agree with the statement, but I don't think it to be a joke, per say, as generalized as it is (in fact you can end off with with far more then two problems).
DeaD_EyE likes this post
Sig:
>>> import this

The UNIX philosophy: "Do one thing, and do it well."

"The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse

"Everything should be made as simple as possible, but not simpler." :~ Albert Einstein
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  extract substring from a string before a word !! evilcode1 3 491 Nov-08-2023, 12:18 AM
Last Post: evilcode1
  [SOLVED] [regex] Why isn't possible substring ignored? Winfried 4 1,016 Apr-08-2023, 06:36 PM
Last Post: Winfried
  Match substring using regex Pavel_47 6 1,370 Jul-18-2022, 07:46 AM
Last Post: Pavel_47
  ValueError: Found input variables with inconsistent numbers of samples saoko 0 2,433 Jun-16-2022, 06:59 PM
Last Post: saoko
  Substring Counting shelbyahn 4 6,071 Jan-13-2022, 10:08 AM
Last Post: krisputas
  Python Substring muzikman 4 2,264 Dec-01-2020, 03:07 PM
Last Post: deanhystad
  How can I found how many numbers are there in a Collatz Sequence that I found? cananb 2 2,506 Nov-23-2020, 05:15 PM
Last Post: cananb
  Removing items from list if containing a substring pythonnewbie138 2 2,153 Aug-27-2020, 10:20 PM
Last Post: pythonnewbie138
  Substring and If then Condition to create column Chandan 2 2,320 Jan-23-2020, 08:40 AM
Last Post: buran
  ValueError: substring not found hoangthai10788 2 4,563 Sep-23-2019, 05:34 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020