3

[Preamble]:
I am new to Python and am using Python v3.3 on Windows 7 [32-Bit]. Having read around here on stackoverflow about dictionaries and how to add new key:value pairs to a new or pre-existing dictionary, I have found some good information. However, I have not found a solution for the problem below.

[Problem]:
I want to create an empty dictionary that will dynamically allocate the appropriate number of keys based on the number of elements in a list (read from lines in a file), assigning the value to the corresponding key.
Note: (elements in the list are the outputs of each line in the file, delimited by a ' \ ' and are also the values to be assigned to the keys).


[Working Section]:

#listMusic.py
import os; from fnmatch import fnmatch

# This works like a charm for producing a file with the output of the
# absolute paths we want to grab our list elements from.    
def getWorkingPath(rootPath):
    outputFile = open('output.txt', 'w')
    filePattern = "*.mp3"
    for path, subdirs, files in os.walk(rootPath):
        for name in files:
            if fnmatch(name, filePattern):
                path_list = os.path.join(path, name + "\n")
                outputData = outputFile.write(path_list)
    outputFile.close()

# def setPathList():
    '''continued in [Tried Section]'''
rootPath = getWorkingPath(input('Enter a path to crawl: '))<br>

[Working Run]:
C:\> cd C:\Python33\Projects
C:\Python33\Projects>listMusic.py
Enter a path to crawl: 'M:\Music'
...
C:\Python33\Projects> notepad output.txt


[Output]: output.txt
M:\Music\Artist1\Album1\Track1.mp3
M:\Music\Artist1\Album1\Track2.mp3
M:\Music\Artist1\Album2\Track1.mp3
M:\Music\Artist1\Album2\Track2.mp3
M:\Music\Artist2\Album1\Track1.mp3
M:\Music\Artist2\Album1\Track2.mp3
M:\Music\UnOrdered\Track1.mp3
M:\Music\UnOrdered\Track2.mp3
... (and so-forth)...


[Tried Section]:

...
...    
def setPathList():
    for i in open(r'output.txt', 'r'):
        v = i.rstrip("\n").split(os.sep)
        k = {'drive':v[0], 'directory':v[1], 'artist':v[2],
               'album':v[3], 'track':v[4]}
        print(k)
rootPath = getWorkingPath(input('Enter a path to crawl: '))

When entering the same code from the function setPathList() interactively,
the output is as expected (if there are 5 elements in the value list...fails if path is out of range) :

[Tried Run]:
C:\>Python
Python 3.3.2 [MSC v.1600 32 bit (Intel)] on win32
>>>

for i in open(r'output.txt', 'r'):
    v = i.rstrip("\n").split(os.sep)
    k = {'drive':v[0], 'directory':v[1], 'artist':v[2],
               'album':v[3], 'track':v[4]}
    print(k)

...
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist1', 'album': 'Album1', 'track': 'Track1.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist1', 'album': 'Album1', 'track': 'Track2.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist1', 'album': 'Album2', 'track': 'Track1.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist1', 'album': 'Album2', 'track': 'Track2.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist2', 'album': 'Album1', 'track': 'Track1.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist2', 'album': 'Album1', 'track': 'Track2.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist2', 'album': 'Album2', 'track': 'Track1.mp3'}
{'drive': 'M:', 'directory': 'Music', 'artist': 'Artist2', 'album': 'Album2', 'track': 'Track2.mp3'}

Traceback (most recent call last):
File "[stdin]", line 3, in [module]
IndexError: list index out of range
C:\>


And completely fails when running the module:
C:\> python -i listMusic.py
>>> print(k)
Traceback (most recent call last):
File "[stdin]", line 1, in [module]
NameError: name 'k' is not defined


So I need a way to make a dictionary that creates keys to match the values from file, as well as a proper way of grabbing the dictionary.


[Resources]:
How do I read a file line-by-line into a list?
How to split a dos path into its components in Python

[Final Thoughts]:
I am sure that I am probably missing some simple yet vital part to this script to get the desired output. As I said, I am new to python and the majority of this script was pieced together from my (loose/broken) understanding of the language. Answered vote will be those that give a good, coherent explanation of the logic for producing the result.
Community
  • 1
  • 1
Kevin
  • 43
  • 4

2 Answers2

1

These entries

M:\Music\UnOrdered\Track1.mp3
M:\Music\UnOrdered\Track2.mp3

can not be split into five parts on os.sep. There are only four parts.

  • This note was mentioned in the tried section: (if there are 5 entries in the value list....fails if path is out of range). – Kevin Nov 06 '13 at 17:30
0

The problem that I think you are trying to solve, is that you do not know in advance how many "pieces" of the path you will end up having. This will make it very hard to make the assumption "Oh, okay this second part is the artist, this third part is the album..." etc. when you are not certain to have a specific path layout.

So I think one option would be that if you KNOW that you will only have the two cases, then handle the cases separately:

for i in open(r'output.txt', 'r'):
    k = {}
    v = i.rstrip("\n").split(os.sep)
    k = {'drive':v[0], 'directory':v[1], 'artist':v[2]}
    if len(v) > 4:    # OR: if 'Unordered' not in v:
        k['album'] = v[3]
        k['track'] = v[4]
    else:
        k['track'] = v[3]
    print( k)

But I think you may also want to consider the case where the "directory" may NOT be just one level under the root? For example if your tracks are in M:\MyFolder\Music then everything is off in the assumption of what "directory" is.

The bottom line is that if you don't know the potential layout of the folders going in, I think there's a lot of possibility for making wrong assumptions.

Grizz
  • 320
  • 1
  • 11