morea030
morea030

Reputation: 430

Getting no such file or directory even though it exists

I have a script that loads songs and each song's data from a db (using peewee) and then downloads each song.

for music in musiclibrary.select().where(musiclibrary.downloaded == 0):

    if not os.path.exists("mp3s/" + music.category + "/" + music.artist_name):
        os.makedirs("mp3s/" + music.category + "/" + music.artist_name)

    if not os.path.exists("mp3s/" + music.category + "/" + music.artist_name + 
                          "/" + music.album_name):
        os.makedirs("mp3s/" + music.category + "/" + music.artist_name + 
                    "/" + music.album_name)

    sub_dir = ("mp3s/" + music.category + "/" + music.artist_name + 
               "/" + music.album_name)

    song = requests.get(music.song_mp3_url, timeout=(3,9))
    if song.status_code == 200:              
        try:
            with open(os.path.join(sub_dir, song_name), "wb") as f:
                for chunk in song.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
        except Exception as e:
            print "exp is", e
                return

I'm getting

exp is [Errno 2] No such file or directory: u'mp3s/letmiat/\u0627\u0644\u0633\u064a\u062f \u062d\u0633\u064a\u0646 \u0627\u0644\u0645\u0627\u0644\u0643\u064a/\u0644\u0637\u0645\u064a\u0627\u062a \u0645\u062a\u0641\u0631\u0642\u0629 \\\u06357\u0644\u0645\u0627\u0644\u0643\u064a/\u0644\u0637\u0645\u064a7\u0644\u0645\u0627\u0644\u0643\u064a/\u0644\u0637\u0645\u064a\u0627\u062a.mp3

This error occurs even though the directory already exists. The song name, album name, and artist name are mostly Arabic. I'm running this under Windows.

EDIT

I have a script (run.py) that calls this script (downloader.py) after some other script (written in scrapy) finnishes. run.py is in the project root folder, and downloader.py is one level under it. Just to be sure, I've put the mp3s folder in both places. Here is how it looks

-project
  --run.py
  --mp3s
    ---downloader.py
    ---mp3s

Upvotes: 0

Views: 1710

Answers (2)

Eryk Sun
Eryk Sun

Reputation: 34270

If I split the name reported in the error on "/", I get 6 components instead of 5, and one of the components is actually 2 because it contains " \", i.e. a space followed by a backslash. That's two problems. Obviously the embedded backslash is a problem. Also, the first component in this pair ends in a space. Windows strips off this space character when os.makedirs creates the directory. However, Windows does not strip off the trailing space from a non-final path component, such as when you try to create the mp3 file.

You need to ensure each path component is valid, i.e. that it contains no reserved characters -- i.e. ASCII control characters (ordinals 0-31), backslash, forward slash, pipe, colon, or the wildcard characters (question mark, asterisk, less than, greater than, and double quote); is not a DOS device name (CON, CONIN$, CONOUT$, PRN, AUX, NUL, COM[1-9], and LPT[1-9]); and doesn't end with a space or period (dot).

Upvotes: 1

jfbeltran
jfbeltran

Reputation: 1818

Verify that it is not a unicode issue by writting a test:

def test_ascii_writing():
    with open('test.txt', "w") as f:
          f.write('TESTING')

def test_unicode_writing():
    with open(u'\u0627.txt', "w") as f:
          f.write('TESTING')


test_ascii_writing()
test_unicode_writing()

If that test passes, I would guess the problem is you're assuming the category/artist/album folder chain already exists when it doesn't.

If you have a folder called mp3 and it is empty, and want to write the file for the song "Come Together" by The Beatles:

import os
os.mkdir('mp3/Rock')
os.mkdir('mp3/Rock/Beatles')
os.mkdir('mp3/Rock/Beatles/AbbeyRoad')

Before you can do:

with open('mp3/Rock/Beatles/AbbeyRoad', "wb") as f:
    for chunk in song.iter_content(chunk_size=1024):
        if chunk:
            f.write(chunk)

Upvotes: 1

Related Questions