0

I'm trying to track how many times a selection was made in a 2D array and how many times it was played in another array (it has to deal with having multiple mp3's in a directory). Not even sure I'm describing it well, but hopefully my example will show my issue.

If you take the code below (and don't have the "PlayHistory.csv" file created), run it, type "A1" you will see two 2D arrays print out. Specifically look at entries for "A1". The Selection Count is 0 and Allowed Selection Count is 1. This is what I'd expect. Now, close the program (or IDE in my case) the "PlayHistory.csv" file is present and notice A1 entry is 0). Run the program again and use "A1" as your input and you'll see both the Selection Count is 1 and the Allowed Selection Count is 1. I'm not even updating the SelectionCount array in the attached code. How is this happening?

#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
AllowedCount = []
Sel_char = None
Queue_counter = 0
Play_counter = 0
PlayHistory="PlayHistory.csv"
#
# Create/Find/Open PlayHistory.csv
# Create media folders as needed if new PlayHistory file is created
#
USBDrive =  os.path.join("/media/pi", "USB30FD")
if os.path.isfile(os.path.join(USBDrive, PlayHistory)):
    datafile = open(os.path.join(USBDrive, PlayHistory), 'r+')
    datareader = csv.reader(datafile, delimiter=',')
    for row in datareader:
        SelectionCount.append(row)
        AllowedCount.append(row)
else:
    datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
    datawriter = csv.writer(datafile, delimiter=',')
    datawriter.writerow(['Selection', 'Count'])
    SelectionCount.append(['Selection', 'Count'])
    AllowedCount.append(['Selection', 'Count'])
    for x in range (65, 87):
        if x == 73 or x == 79:
            continue
        for y in range (1,11):
            if y == 10:
                datawriter.writerow([chr(x) + str(0),0])
                SelectionCount.append([chr(x) + str(0),0])
                AllowedCount.append([chr(x) + str(0),0])
#               if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(0))):
#                   os.makedirs(os.path.join(USBDrive, chr(x) + str(0)))
            else:
                datawriter.writerow([chr(x) + str(y),0])
                SelectionCount.append([chr(x) + str(y),0])
                AllowedCount.append([chr(x) + str(y),0])
#               if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(y))):
#                   os.makedirs(os.path.join(USBDrive, chr(x) + str(y)))
    datafile.flush()
datafile.close()
#AllowedCount == SelectionCount

#
# Find location of Selection in SelectionCount 2D array
#
def find(l, elem):
    for row, i in enumerate(l):
        try:
            column = i.index(elem)
        except ValueError:
            continue
        return row, column
    return -1
#
# MediaPlayer function
#
def QueueTracker(tracker, selection):
    global Queue_counter, Play_counter
    if tracker == "Queue":
        Queue_counter = Queue_counter + 1
    elif tracker == "Play":
        print("Play Counter")
        Play_counter = Play_counter + 1
        count1,count2=find(SelectionCount, selection)
        #SelectionCount[count1][1] = int(SelectionCount[count1][1]) + 1
        print("SelectionCount: " + str(SelectionCount[count1][1]))
    elif tracker == "Allowed":
        print("Allowed Counter")
        acount1,acount2=find(AllowedCount, selection)
        print(AllowedCount[acount1][1])
        AllowedCount[acount1][1] = int(AllowedCount[acount1][1]) + 1
        print("AllowedSelectionCount: " + str(AllowedCount[acount1][1]))
        print("Selected Count")
        print(SelectionCount)
        print("Allowed Selection Count")
        print(AllowedCount)

#
# Define keyboard actions
#
def on_press(key):
    global Action
    try:
        Sel_char = int(key.char)
    except:
        try:
            Sel_char = str(key.char)
            Sel_char = Sel_char.upper()
        except:
            Sel_char = None
    if Sel_char == "Z":
        return False
    elif Sel_char == "Y":
        print("Play Track")
        QueueTracker("Played", "A1")
    elif type(Sel_char) == str:
        Action = Sel_char
    elif type(Sel_char) == int:
        Action = Action + str(Sel_char)
        QueueTracker("Allowed", "A1")
    else:
        pass
# Read keyboard input
#
print("Ready...")
with Listener(on_press=on_press) as listener:
    listener.join()
#
# Program is shutting down
#
print ("")
print ("Writing Play Counts to PlayHistory file")
datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
datawriter = csv.writer(datafile, delimiter=',')
datawriter.writerows(SelectionCount)
datafile.flush()
datafile.close()

print ("")
print ("Have a nice day!")
print ("")
sys.exit()

Any help would be greatly appreciated.

Thanks! Brian

Brian
  • 93
  • 1
  • 11
  • [How to debug small programs.](//ericlippert.com/2014/03/05/how-to-debug-small-programs/) | [What is a debugger and how can it help me diagnose problems?](//stackoverflow.com/q/25385173/843953) Step through your code and observe where the intermediate results deviate from the ones you expect. Then narrow down the problem into a [mre]. Then ask a specific question. _"Why is my code doing this"_ is [too broad for Stack Overflow.](//meta.stackoverflow.com/a/253788/843953) Please also take the [tour], read [ask] and [what's on-topic](/help/on-topic). Welcome to Stack Overflow! – Pranav Hosangadi Mar 15 '21 at 21:11
  • @PranavHosangadi - (totally off-topic...sorry) How did you get all those links into your comment? Seems that all those links would take you well past the limit. – CryptoFool Mar 15 '21 at 23:09
  • @CryptoFool https://stackoverflow.com/editing-help#comment-formatting I use the shorthand links for `[tour]` and `[ask]`, omit the `https://stackoverflow.com` from other SO links `[what's on-topic](/help/on-topic)` and omit the protocol for external links `[How to debug small programs.](//ericlippert.com/2014/03/05/how-to-debug-small-programs/)` – Pranav Hosangadi Mar 16 '21 at 13:43
  • Cool. Thanks for the explanation! I had found `[tour]`, `[ask]` and such, but being able to drop the protocol and whole `https://stackoverflow.com` is a great thing to know. Thanks so much for taking the time to respond. – CryptoFool Mar 16 '21 at 13:56

1 Answers1

1

Your assessment was essentially correct:

    for row in datareader:
        SelectionCount.append(row)
        AllowedCount.append(row)

That does not make two copies. That makes two pointers to one list. If you modify the list in SelectionCount[0], that will also modify AllowedCount[0]. Change that to

    for row in datareader:
        SelectionCount.append(row)
        AllowedCount.append(row[:])

You might also consider this simplification to your first loop creating the CSV data:

    for x in 'ABCDEFGHJKLMNPQRSTUV':
        for y in range (10):
            datawriter.writerow([x + str(y),0])
            SelectionCount.append([x + str(y),0])
            AllowedCount.append([x + str(y),0])
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • By the way, if you're running on Windows, you should add `newline=''` when you open the CSV file for writing, otherwise you end up with CR,CR,LF. – Tim Roberts Mar 15 '21 at 21:29