Исключение Python IOError при создании длинного файла

Я получаю сообщение об ошибке IOError, показанное ниже, при попытке открыть новый файл с помощью «open (fname, 'w+')». Полное сообщение об ошибке приведено ниже.

Файл не существует, но я проверил с помощью «os.access(dir_name, os.W_OK)» и «os.path.exists (dir_name)», что родительский каталог для файла существует.

Мне интересно, слишком ли длинное имя файла для Windows или я делаю что-то не так. Любые советы будут оценены. Большое спасибо.

Сообщение об ошибке:

IOError: [Errno 2] Нет такого файла или каталога: 'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Нерабочие часы для будней\hourly_data_for_2_weeks\1294897740\ json.data\Link\0\Использование ссылок\analyzer393146160-data0.js'


person AshD    schedule 13.01.2011    source источник
comment
Спасибо. Ограничение превышает 260 символов. В статье MSDN упоминается, что мы можем использовать префикс \\?\ для длинного имени файла, просто любопытно, знает ли кто-нибудь, как я могу добавить префикс к имени файла. Когда я пытаюсь выполнить простую операцию +, я получаю сообщение об ошибке EOL при сканировании строки в одинарных кавычках». (fname = '\\?\' + fname)   -  person AshD    schedule 13.01.2011
comment
Использовать \\\\?\\. Необработанная строка не будет работать в этом случае.   -  person cgohlke    schedule 13.01.2011
comment
Вместо этого используйте косую черту. Также см. stackoverflow.com/faq#howtoask.   -  person Johnsyweb    schedule 13.01.2011
comment
Я попытался использовать \\\\?\\ и \\\\UNC\\?\\, добавив их к имени файла, и получил такое же исключение. В любом случае, когда я пытаюсь создать файл в проводнике Windows, он не позволяет мне создать файл (Windows блокирует добавление символов). Я так понимаю это системное ограничение?   -  person AshD    schedule 14.01.2011


Ответы (5)


В Windows API максимальная длина пути ограничена 260 символами.

http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx

Обновление: добавьте «\\?\» к пути.

person cgohlke    schedule 13.01.2011
comment
... в сочетании с очень запутанным значением ошибки; это должно быть ENAMETOOLONG, а не ENOENT. Я думаю, что это одна из тех малоизвестных ошибок Windows, с которыми каждый сталкивался хотя бы раз в какой-то момент своей карьеры. - person Glenn Maynard; 13.01.2011
comment
А как насчет неанглийских языков? Я чувствую, что максимум ниже. - person Vitaly Zdanevich; 08.10.2018

Вот некоторый связанный код, который работает для меня (у меня очень длинные имена файлов и пути):

for d in os.walk(os.getcwd()):
    dirname = d[0]
    files = d[2]
    for f in files:
        long_fname = u"\\\\?\\" + os.getcwd() + u"\\" + dirname + u"\\" + f
        if op.isdir(long_fname):
            continue
        fin = open(long_fname, 'rb')
        ...

Обратите внимание, что для меня это работало только с комбинацией всего следующего:

  1. Добавьте '\\?\' впереди.

  2. Используйте полный путь, а не относительный.

  3. Используйте только обратную косую черту.

  4. В Python строка имени файла должна быть строкой Юникода, например u"abc", а не "abc".

Также обратите внимание, по какой-то причине os.walk(..) вернул некоторые каталоги в виде файлов, поэтому выше я проверил это.

person Evgeni Sergeev    schedule 04.11.2012
comment
Большое спасибо за упоминание о том, что строка Python должна быть строкой Unicode — это спасло меня! - person Frerich Raabe; 05.11.2015
comment
os.getcwd() исправил это для меня. Должен быть весь путь, а не только относительный путь. - person Blairg23; 23.06.2016

Вы можете исправить модуль tarfile следующим образом:

import tarfile

def monkey_patch_tarfile():
    import os
    import sys
    if sys.platform not in ['cygwin', 'win32']:
        return
    def long_open(name, *args, **kwargs):
    # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx#maxpath
        if len(name) >= 200:
            if not os.path.isabs(name):
                name = os.path.join(os.getcwd(), name)
            name = "\\\\?\\" + os.path.normpath(name)
        return long_open.bltn_open(name, *args, **kwargs)
    long_open.bltn_open = tarfile.bltn_open
    tarfile.bltn_open = long_open

monkey_patch_tarfile()
person ticapix    schedule 18.10.2013

Если это не длина имени файла, это содержимое имени файла...

Python рассматривает «\12» как управляющую последовательность.

>>> fn='C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for
>>> fn=r'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'
>>> print fn
C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js
weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js' >>> print fn C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12bcde_corporate_nov_12.projectbcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for
>>> fn=r'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'
>>> print fn
C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js
weeks 94897740\json.data\Link\Link Utilizationnalyzer393146160-data0.js

Использование необработанных строк для имен файлов Windows поможет:

>>> fn=r'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'
>>> print fn
C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js

Обновить

В качестве альтернативы используйте прямую косую черту «/» вместо обратной косой черты «\», поскольку они будут работать во всех операционных системах и избавят вас от проблем с обратной косой чертой в конце пути, как в ваших комментариях.

См. также os.path.join() .

Обновление 2

Упрощенная демонстрация проблемы:

>>> open('.\12\n\r\file.txt')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: '.\n\n\r\x0cile.txt'
>>> open('./12/n/r/file.txt')
<open file './12/n/r/file.txt', mode 'r' at 0x7ff83f98>

C:\Users\johnysweb>copy .\12\n\r\file.txt con
Blah
        1 file(s) copied.
person Johnsyweb    schedule 13.01.2011
comment
Вам лучше постоянно использовать косую черту; они отлично работают в Windows, и в результате получается код, который с большей вероятностью будет работать на других платформах. - person Glenn Maynard; 13.01.2011
comment
ОП использовал правильно закодированный путь к файлу. В противном случае сообщение об ошибке было бы другим (TypeError). - person cgohlke; 14.01.2011
comment
@cgohlke: Пожалуйста, посмотрите мое второе обновление, которое демонстрирует исключение IOError с тем же текстом, что и OP. - person Johnsyweb; 14.01.2011
comment
Я действительно думаю, что кодировка правильная, так как я только что попробовал другое имя файла (sm.txt с полным путем), которое удерживает меня в пределах 260 символов, и это сработало без исключения. Я вижу, что файл создается. - person AshD; 14.01.2011
comment
@Johnsyweb: я не сомневаюсь, что можно получить IOError, используя неправильно закодированные имена путей. Однако имя пути, используемое OP, содержит NULL байт \0, и это приведет к ошибке TypeError в функции открытия. Также маловероятно, что имя пути длиной более 260 символов было введено OP вручную. Скорее всего, это был результат вызова функции. - person cgohlke; 14.01.2011
comment
Это имеет смысл. Благодарю за разъяснение. - person Johnsyweb; 14.01.2011

Проверьте длину всего пути, а затем добавьте необходимый формат длинного пути Windows. Следует отметить, что это не работает для доступа к данным из удаленных каталогов, то есть путей, начинающихся с «\\some_remote_location\..», поэтому вам нужно будет сопоставить этот каталог локально, чтобы «длинный путь» работал.

if len(path_and_file) > 250: #I think the max is 260 but I left a buffer :)
    path_and_file = '\\\\?\\'+path_and_file
person sparrow    schedule 14.03.2019