os.path.join(p1,p2) опускает косые черты p1

Я программист в свободное время, поэтому, пожалуйста, будьте нежны. Теперь, что касается реальной проблемы, один из моих пользователей сталкивается со странным поведением, когда os.path.join(p1,p2) возвращает относительный путь со всеми косыми чертами, опущенными из p1. Вот так (притворяясь, что это делается в интерпретаторе строки cmd python):

>>import os
>>p1 = "/Some/Path/Tosmth"
>>p2 = "file.ext"
>>print os.path.join(p1,p2)`

Тогда вывод:

>>"SomePathTosmth/file.ext"

Непосредственно перед операцией соединения я проверил содержимое p1 и p2, и это именно то, что я ожидал. Вот фактическая рассматриваемая реализация с некоторым дополнительным кодом отладки:

   def __moveMovie(self, src, dst, folder, file_name):
    try:
        self.logDebug('__moveMovie(): src=%s | dst=%s | folder=%s | file_name=%s' % (src, dst, folder, file_name))
        dest = save_path(dst)
        file_name = save_path(file_name)
        if self.getConfig("subfolder") is True:
            dest = os.path.join(dst,folder)
            os.mkdir(Utils().encode(dest))
    except OSError, e:
        if e.args[0] == 17:
            self.logDebug(u'Cannot create folder "%s". It already exists.' % os.path.join(dest))
    try:
        full_dst = Utils().encode(os.path.join(dest,file_name))
        self.logDebug('var "full_dst" w/o encode: %s' % os.path.join(dest, file_name))
        self.logDebug('var "full_dst" w/ encode: %s' % Utils().encode(os.path.join(dest,file_name)))
        if os.path.exists(full_dst):
            pass
        shutil.move(src, full_dst)
        self.logInfo(u'Movie "%s" moved to "%s"' % (os.path.split(src)[1], os.path.join(dest,file_name)))
        self.__movie_queue.task_done()
    except OSError, e:
        if e.args[0] == 21:
            self.logDebug(u'Cannot move "%s" to "%s". "%s" is a directory.' % (os.path.split(src)[1],
                                                                               os.path.join(dest, file_name),
                                                                               os.path.join(dest, file_name)))
            self.__movie_queue.task_done()

Это журнал для этого кода:

05.06.2013 17:29:12 DEBUG     MovieMover: __moveMovie(): src=/var/raid/Daten/Neu/abgezockt.tc.72-ps/Voll.Abgezockt.2013.UNRATED.GERMAN.AC3LD.5.1.DL.720p.BluRay.x264-DerSchuft.mkv | dst=/var/raid/Daten/Filme | folder=Voll.Abgezockt.2013.UNRATED.GERMAN.AC3LD.5.1.DL.720p.BluRay.x264-DerSchuft | file_name=Voll Abgezockt.mkv
05.06.2013 17:29:12 DEBUG     MovieMover: var "full_dst" w/o encode: varraidDatenFilme/Voll Abgezockt.mkv
05.06.2013 17:29:12 DEBUG     MovieMover: var "full_dst" w/ encode: varraidDatenFilme/Voll Abgezockt.mkv
05.06.2013 17:29:12 DEBUG     MovieMover: __moveMovie(): src=/var/raid/Daten/Neu/abgezockt.tc.72-ps/.AppleDouble/Voll.Abgezockt.2013.UNRATED.GERMAN.AC3LD.5.1.DL.720p.BluRay.x264-DerSchuft.mkv | dst=/var/raid/Daten/Filme | folder=Voll.Abgezockt.2013.UNRATED.GERMAN.AC3LD.5.1.DL.720p.BluRay.x264-DerSchuft | file_name=Voll Abgezockt.mkv
05.06.2013 17:29:12 DEBUG     MovieMover: var "full_dst" w/o encode: varraidDatenFilme/Voll Abgezockt.mkv
05.06.2013 17:29:12 DEBUG     MovieMover: var "full_dst" w/ encode: varraidDatenFilme/Voll Abgezockt.mkv
Exception in thread Thread-1072:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/var/local/pyload/userplugins/hooks/MovieMover.py", line 360, in __getMvQueue
    self.__moveMovie(src, dst, movie.folder_name, movie.file_name)
  File "/var/local/pyload/userplugins/hooks/MovieMover.py", line 382, in __moveMovie
    shutil.move(src, full_dst)
  File "/usr/lib/python2.7/shutil.py", line 301, in move
    copy2(src, real_dst)
  File "/usr/lib/python2.7/shutil.py", line 130, in copy2
    copyfile(src, dst)
  File "/usr/lib/python2.7/shutil.py", line 83, in copyfile
    with open(dst, 'wb') as fdst:
IOError: [Errno 2] No such file or directory: u'varraidDatenFilme/Voll Abgezockt.mkv'

Exception in thread Thread-1074:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/var/local/pyload/userplugins/hooks/MovieMover.py", line 360, in __getMvQueue
    self.__moveMovie(src, dst, movie.folder_name, movie.file_name)
  File "/var/local/pyload/userplugins/hooks/MovieMover.py", line 382, in __moveMovie
    shutil.move(src, full_dst)
  File "/usr/lib/python2.7/shutil.py", line 301, in move
    copy2(src, real_dst)
  File "/usr/lib/python2.7/shutil.py", line 130, in copy2
    copyfile(src, dst)
  File "/usr/lib/python2.7/shutil.py", line 83, in copyfile
    with open(dst, 'wb') as fdst:
IOError: [Errno 2] No such file or directory: u'varraidDatenFilme/Voll Abgezockt.mkv'

Я в полной растерянности, поскольку функция кодирования, включающая функцию os.path.join(), не является причиной, и когда он выполняет os.path.join() со своим интерпретатором строки cmd python, результат правильный. Я пишу на 2.5, пока он выполняет код на 2.7.2, если это представляет интерес. Я надеюсь, что кто-то сможет пролить свет на это. Благодарю вас!

Поскольку кажется, что я не могу использовать форматирование кода в комментариях, я отвечу здесь:

Это функция save_path():

def save_path(name):
    #remove some chars
    if os.name == 'nt':
        return remove_chars(name, '/\\?%*:|"<>')
    else:
        return remove_chars(name, '/\\"')

Теперь я должен добавить, что это не мой код. Я пишу для проекта с открытым исходным кодом под названием pyLoad. Просто хочу убедиться, что я не утверждаю, что это мой код, хотя на самом деле это не так.

РЕДАКТИРОВАТЬ: ответ Брендана Лонга кажется точным. В моей среде разработки self.getConfig("subfolder") было включено/True, хотя, похоже, это не для моего пользователя. С этим я смог успешно воспроизвести ошибку. Я выпущу это исправление и позволю пользователю подтвердить, что оно работает, но пока все указывает на то, что виновником является save_path. Кроме того, чувствуешь себя немного идиотом из-за того, что не замечаешь очевидного. В любом случае спасибо, и я вернусь к вам с результатом.


person Sven M.    schedule 06.06.2013    source источник
comment
Я добавил это к актуальному вопросу.   -  person Sven M.    schedule 06.06.2013
comment
Первая часть отлично работает в 2.7   -  person Serial    schedule 06.06.2013


Ответы (1)


Глядя на save_path:

if os.name == 'nt':
    return remove_chars(name, '/\\?%*:|"<>')
else:
    return remove_chars(name, '/\\"')

Эта функция удаляет / (и пару других вещей, которые имеют особое значение в именах файлов). Итак... вот почему косые черты удаляются.

Я предполагаю, что эта функция предназначена для очистки имен файлов, загруженных пользователями (чтобы они не могли загрузить файл с именем ../../../etc/passwd). Если в этом нет необходимости, то решение состоит в том, чтобы просто пропустить вызов этой функции.

person Brendan Long    schedule 06.06.2013
comment
Да, должно быть. Поскольку он отлично работает в моей среде разработки, я был настолько уверен, что ошибка происходит дальше по линии, что не обращал слишком много внимания на save_path. Не уверен, почему я использовал его в первую очередь. Также только что успешно воспроизвел это сам. self.getConfig(подпапка) был включен/правда для меня, но, по-видимому, не для моего пользователя. Спасибо за помощь. Я чувствую себя немного идиотом из-за того, что не замечаю очевидного. - person Sven M.; 06.06.2013