Search code examples
pythoncsvfor-loopwhile-loop

paste end of variable name based on i in for loop


I am trying to save each variable save_i (up to length(counter)) as a row in a csv file. Each save variable is defined in a while loop so I have save_1:save_i where i= length(counter). A portion of the code is below:

# Packages
import msvcrt
import time
import sounddevice as sd
import soundfile as sf
import csv


# Settings
PLAY_TIME = 5  # in seconds


# Sound
sound_file_1 = 'C:/Users/am650/Desktop/Audio/aaa_1.mp3'
sound_file_2 = 'C:/Users/am650/Desktop/Audio/aaa_2.mp3'
blast_file_1, fs1 = sf.read(sound_file_1, dtype='float32')
blast_file_2, fs2 = sf.read(sound_file_2, dtype='float32')


# Set Up
time_start = time.perf_counter()
time_stop = time.perf_counter()
time_elapsed = time_stop - time_start
counter = 0

# Basic Logic
while time_elapsed < PLAY_TIME:
    blast = msvcrt.getch()
    if blast == b'1':
        blast = 1
        time_in = time.perf_counter()
        time_to_button_press = time_in - time_start
        sd.play(blast_file_1, device=4)
        status = sd.wait()
        time_in = time.perf_counter()
        time_to_blast_end = time_in - time_start
        counter += 1
        save = "save_"+str(counter)
        globals()[save] = (counter, blast, time_to_button_press, time_to_blast_end)
        print(eval("save_"+str(counter)))
        if time_to_blast_end > PLAY_TIME:
            break
    elif blast == b'2':
        blast = 2
        time_in = time.perf_counter()
        time_to_button_press = time_in - time_start
        sd.play(blast_file_2, device=4)
        status = sd.wait()
        time_in = time.perf_counter()
        time_to_blast_end = time_in - time_start
        counter += 1
        save = "save_"+str(counter)
        globals()[save] = (counter, blast, time_to_button_press, time_to_blast_end)
        print(eval("save_"+str(counter)))
        if time_to_blast_end > PLAY_TIME:
            break
    else:
        print("Invalid Entry")


with open('C:/Users/am650/Desktop/testdata.csv', 'w', newline='') as csvfile:
    datawriter = csv.writer(csvfile, delimiter=' ')
    for i in range(counter):
        datawriter.writerow(eval("save_"+str(i)))

I have tried several variations of that last line of code (datawriter.writerow(eval("save_"+str(i)))), but none of my attempts have worked as expected. The above returns an empty excel sheet. datawriter.writerow("save_"+str(i) returns "save_1", "save_2", etc. up to length(counter) as there own rows instead of the data saved in those variables. datawriter.writerow("save_"+str(counter))gives me the last round of data repeated for i rows (which tells me that the for loop is working okay); additionally, this gives me the last save variable with all components (counter, blast, time_to_button_press, and time_to_blast_end) in one column separated by spaces rather than each component in its own column.

I expect the code to give me an excel sheet that looks something like:

r1: 1, 4, 0.5, 1

r2: 2, 2, 1.7, 2.3

r3: 3, 5, 4, 4.5

etc. where each row has four columns and contains the data from save_1:save_i

Any help would be great :) Please forgive my code's inelegance, I almost exclusively work in r. I have tried to use a bunch of the already answered similar questions and they have gotten me closer to my goal, but not all the way.


Solution

  • I think you are doing a lot of work to manumatically do what a set of lists might do for you. Rather than creating a bunch of variables foo_1, foo_2, ...., foo_n, you probably want to use a list or dictionary to store those.

    Here is how I might initially approach the problem:

    # Packages
    import csv
    import msvcrt
    import time
    
    import sounddevice as sd
    import soundfile as sf
    
    # Settings
    PLAY_TIME = 5  # in seconds
    
    # Sounds
    blast_files = {
        "1": sf.read('C:/Users/am650/Desktop/Audio/aaa_1.mp3', dtype='float32'),
        "q": sf.read('C:/Users/am650/Desktop/Audio/aaa_q.mp3', dtype='float32'),
    }
    save_files = []
    
    counter = 0
    time_start = time.perf_counter()
    time_elapsed = time.perf_counter() - time_start
    
    while time_elapsed < PLAY_TIME:
        blast_key = msvcrt.getch().decode()
        if not blast_key in blast_files:
            print("Invalid Entry")
            time_elapsed = time.perf_counter() - time_start
            continue
    
        counter += 1
     
        time_to_button_press = time.perf_counter() - time_start
        sd.play(blast_files[blast_key], device=4)
        status = sd.wait()
        time_to_blast_end = time.perf_counter() - time_start
     
        save_files.append([counter, blast_key, time_to_button_press, time_to_blast_end])
        time_elapsed = time.perf_counter() - time_start
    
    with open('C:/Users/am650/Desktop/testdata.csv', 'w', newline='') as csvfile:
        datawriter = csv.writer(csvfile, delimiter=' ')
        for row in save_files:
            print(row)  ## just to demonstrate that row here should be an item stored it the list save_files
            datawriter.writerow(row)
    

    I don't have the sound libraries but here is a version that works for me. It accepts inputs of 1 and will print a list of files and construct the csv.

    # Packages
    import csv
    import msvcrt
    import time
    
    # Settings
    PLAY_TIME = 5  # in seconds
    
    # Sounds
    blast_files = {
        "1": 'C:/Users/am650/Desktop/Audio/aaa_1.mp3',
        "q": 'C:/Users/am650/Desktop/Audio/aaa_q.mp3',
    }
    save_files = []
    
    counter = 0
    time_start = time.perf_counter()
    time_elapsed = time.perf_counter() - time_start
    
    while time_elapsed < PLAY_TIME:
        blast_key = msvcrt.getch().decode()
    
        if not blast_key in blast_files:
            print("Invalid Entry")
            time_elapsed = time.perf_counter() - time_start
            continue
    
        counter += 1
     
        time_to_button_press = time.perf_counter() - time_start
        print(blast_files[blast_key])
        time_to_blast_end = time.perf_counter() - time_start
     
        save_files.append([counter, blast_key, time_to_button_press, time_to_blast_end])
        time_elapsed = time.perf_counter() - time_start
    
    with open('testdata.csv', 'w', newline='') as csvfile:
        datawriter = csv.writer(csvfile, delimiter=' ')
        for row in save_files:
            print(row)  ## just to demonstrate that row here should be an item stored it the list save_files
            datawriter.writerow(row)