Автор оригинала: Doug Hellmann.
Цель:
Разбирайте, создавайте, тестируйте и иначе работайте с именами файлов и путями.
Написать код для работы с файлами на нескольких платформах легко с помощью функций, включенных в модуль os.path
. Даже программы, не предназначенные для переноса между платформами, должны использовать os.path
для надежного анализа имени файла.
Парсинг путей
Первый набор функций в os.path
может использоваться для синтаксического анализа строк, представляющих имена файлов, на их составные части. Важно понимать, что эти функции не зависят от реально существующих путей; они действуют исключительно на струнах.
Анализ пути зависит от нескольких переменных, определенных в os:
os.sep
– разделитель между частями пути (например, «/
» или «\
»).os.extsep
– разделитель между именем файла и “расширением” файла (например, “.
“).os.pardir
– компонент пути, который означает переход по дереву каталогов на один уровень вверх (например, «..
»).os.curdir
– компонент пути, который ссылается на текущий каталог (например, «.
»).
Функция split ()
разбивает путь на две отдельные части и возвращает кортеж
с результатами. Второй элемент tuple
– это последний компонент пути, а первый элемент – это все, что предшествует ему.
ospath_split.py
import os.path PATHS [ '/one/two/three', '/one/two/three/', '/', '.', '', ] for path in PATHS: print('{!r:>17} : {}'.format(path, os.path.split(path)))
Когда входной аргумент заканчивается на os.sep
, последний элемент пути является пустой строкой.
$ python3 ospath_split.py '/one/two/three' : ('/one/two', 'three') '/one/two/three/' : ('/one/two/three', '') '/' : ('/', '') '.' : ('', '.') '' : ('', '')
Функция basename ()
возвращает значение, эквивалентное второй части значения split ()
.
ospath_basename.py
import os.path PATHS [ '/one/two/three', '/one/two/three/', '/', '.', '', ] for path in PATHS: print('{!r:>17} : {!r}'.format(path, os.path.basename(path)))
Полный путь сокращается до последнего элемента, независимо от того, относится ли он к файлу или каталогу. Если путь заканчивается разделителем каталогов ( os.sep
), базовая часть считается пустой.
$ python3 ospath_basename.py '/one/two/three' : 'three' '/one/two/three/' : '' '/' : '' '.' : '.' '' : ''
Функция dirname ()
возвращает первую часть разделенного пути:
ospath_dirname.py
import os.path PATHS [ '/one/two/three', '/one/two/three/', '/', '.', '', ] for path in PATHS: print('{!r:>17} : {!r}'.format(path, os.path.dirname(path)))
Объединение результатов basename ()
с dirname ()
дает исходный путь.
$ python3 ospath_dirname.py '/one/two/three' : '/one/two' '/one/two/three/' : '/one/two/three' '/' : '/' '.' : '' '' : ''
splitext ()
работает аналогично split ()
, но разделяет путь по разделителю расширения, а не по разделителю каталогов.
ospath_splitext.py
import os.path PATHS [ 'filename.txt', 'filename', '/path/to/filename.txt', '/', '', 'my-archive.tar.gz', 'no-extension.', ] for path in PATHS: print('{!r:>21} : {!r}'.format(path, os.path.splitext(path)))
При поиске расширения используется только последнее вхождение os.extsep
, поэтому, если имя файла имеет несколько расширений, в результате разделения остается часть расширения на префиксе.
$ python3 ospath_splitext.py 'filename.txt' : ('filename', '.txt') 'filename' : ('filename', '') '/path/to/filename.txt' : ('/path/to/filename', '.txt') '/' : ('/', '') '' : ('', '') 'my-archive.tar.gz' : ('my-archive.tar', '.gz') 'no-extension.' : ('no-extension', '.')
commonprefix ()
принимает список путей в качестве аргумента и возвращает единственную строку, представляющую общий префикс, присутствующий во всех путях. Значение может представлять путь, который на самом деле не существует, и разделитель путей не учитывается, поэтому префикс может не останавливаться на границе разделителя.
ospath_commonprefix.py
import os.path paths ['/one/two/three/four', '/one/two/threefold', '/one/two/three/', ] for path in paths: print('PATH:', path) print() print('PREFIX:', os.path.commonprefix(paths))
В этом примере общая строка префикса – /one/two/three
, хотя один путь не включает каталог с именем three
.
$ python3 ospath_commonprefix.py PATH: /one/two/three/four PATH: /one/two/threefold PATH: /one/two/three/ PREFIX: /one/two/three
commonpath ()
учитывает разделители путей и возвращает префикс, который не включает частичные значения пути.
ospath_commonpath.py
import os.path paths ['/one/two/three/four', '/one/two/threefold', '/one/two/three/', ] for path in paths: print('PATH:', path) print() print('PREFIX:', os.path.commonpath(paths))
Поскольку "тройной"
не имеет разделителя пути после "три"
, общий префикс – /one/two
.
$ python3 ospath_commonpath.py PATH: /one/two/three/four PATH: /one/two/threefold PATH: /one/two/three/ PREFIX: /one/two
Строительные пути
Помимо разделения существующих путей, часто необходимо построить пути из других строк. Чтобы объединить несколько компонентов пути в одно значение, используйте join ()
:
ospath_join.py
import os.path PATHS [ ('one', 'two', 'three'), ('/', 'one', 'two', 'three'), ('/one', '/two', '/three'), ] for parts in PATHS: print('{} : {!r}'.format(parts, os.path.join(*parts)))
Если какой-либо аргумент для соединения начинается с os.sep
, все предыдущие аргументы отбрасываются, а новый становится началом возвращаемого значения.
$ python3 ospath_join.py ('one', 'two', 'three') : 'one/two/three' ('/', 'one', 'two', 'three') : '/one/two/three' ('/one', '/two', '/three') : '/three'
Также можно работать с путями, которые включают «переменные» компоненты, которые могут быть расширены автоматически. Например, expanduser ()
преобразует символ тильды ( ~
) в имя домашнего каталога пользователя.
ospath_expanduser.py
import os.path for user in ['', 'dhellmann', 'nosuchuser']: lookup '~' + user print('{!r:>15} : {!r}'.format( lookup, os.path.expanduser(lookup)))
Если домашний каталог пользователя не может быть найден, строка возвращается без изменений, как в случае с ~ nosuchuser
в этом примере.
$ python3 ospath_expanduser.py '~' : '/Users/dhellmann' '~dhellmann' : '/Users/dhellmann' '~nosuchuser' : '~nosuchuser'
expandvars ()
является более общим и расширяет любые переменные среды оболочки, присутствующие в пути.
ospath_expandvars.py
import os.path import os os.environ['MYVAR'] 'VALUE' print(os.path.expandvars('/path/to/$MYVAR'))
Проверка не выполняется, чтобы гарантировать, что значение переменной приводит к имени уже существующего файла.
$ python3 ospath_expandvars.py /path/to/VALUE
Нормализация путей
Пути, собранные из отдельных строк с помощью join ()
или со встроенными переменными, могут закончиться дополнительными разделителями или компонентами относительного пути. Используйте normpath ()
, чтобы очистить их:
ospath_normpath.py
import os.path PATHS [ 'one//two//three', 'one/./two/./three', 'one/../alt/two/three', ] for path in PATHS: print('{!r:>22} : {!r}'.format(path, os.path.normpath(path)))
Сегменты пути, состоящие из os.curdir
и os.pardir
, оцениваются и сворачиваются.
$ python3 ospath_normpath.py 'one//two//three' : 'one/two/three' 'one/./two/./three' : 'one/two/three' 'one/../alt/two/three' : 'alt/two/three'
Чтобы преобразовать относительный путь в абсолютное имя файла, используйте abspath ()
.
ospath_abspath.py
import os import os.path os.chdir('/usr') PATHS [ '.', '..', './one/two/three', '../one/two/three', ] for path in PATHS: print('{!r:>21} : {!r}'.format(path, os.path.abspath(path)))
В результате получается полный путь, начинающийся с вершины дерева файловой системы.
$ python3 ospath_abspath.py '.' : '/usr' '..' : '/' './one/two/three' : '/usr/one/two/three' '../one/two/three' : '/one/two/three'
Файловое время
Помимо работы с путями, os.path
включает функции для получения свойств файла, аналогичные тем, которые возвращает os.stat ()
:
ospath_properties.py
import os.path import time print('File :', __file__) print('Access time :', time.ctime(os.path.getatime(__file__))) print('Modified time:', time.ctime(os.path.getmtime(__file__))) print('Change time :', time.ctime(os.path.getctime(__file__))) print('Size :', os.path.getsize(__file__))
os.path.getatime ()
возвращает время доступа, os.path.getmtime ()
возвращает время модификации, а os.path.getctime ()
возвращает время создания. os.path.getsize ()
возвращает количество данных в файле, представленное в байтах.
$ python3 ospath_properties.py File : ospath_properties.py Access time : Sun Mar 18 16:21:22 2018 Modified time: Fri Nov 11 17:18:44 2016 Change time : Fri Nov 11 17:18:44 2016 Size : 481
Тестирование файлов
Когда программа встречает имя пути, ей часто необходимо знать, относится ли этот путь к файлу, каталогу или символической ссылке и существует ли он. os.path
включает функции для проверки всех этих условий.
ospath_tests.py
import os.path FILENAMES [ __file__, os.path.dirname(__file__), '/', './broken_link', ] for file in FILENAMES: print('File : {!r}'.format(file)) print('Absolute :', os.path.isabs(file)) print('Is File? :', os.path.isfile(file)) print('Is Dir? :', os.path.isdir(file)) print('Is Link? :', os.path.islink(file)) print('Mountpoint? :', os.path.ismount(file)) print('Exists? :', os.path.exists(file)) print('Link Exists?:', os.path.lexists(file)) print()
Все тестовые функции возвращают логические значения.
$ ln -s /does/not/exist broken_link $ python3 ospath_tests.py File : 'ospath_tests.py' Absolute : False Is File? : True Is Dir? : False Is Link? : False Mountpoint? : False Exists? : True Link Exists?: True File : '' Absolute : False Is File? : False Is Dir? : False Is Link? : False Mountpoint? : False Exists? : False Link Exists?: False File : '/' Absolute : True Is File? : False Is Dir? : True Is Link? : False Mountpoint? : True Exists? : True Link Exists?: True File : './broken_link' Absolute : False Is File? : False Is Dir? : False Is Link? : True Mountpoint? : False Exists? : False Link Exists?: True
Смотрите также
- стандартная библиотечная документация для os.path
- Заметки о переносе Python 2 на 3 для os.path
- pathlib – Пути как объекты.
- os – модуль
os
является родительским дляos.path
. - time – модуль времени включает функции для преобразования между представлением, используемым функциями свойств времени в
os.path
, и удобными для чтения строками.