Path for: path for — Перевод на русский — примеры английский
path for — Перевод на русский — примеры английский
На основании Вашего запроса эти примеры могут содержать грубую лексику.
На основании Вашего запроса эти примеры могут содержать разговорную лексику.
You didn’t clear a path for the body.
The P6 have provided the path for negotiations which will become necessary when we are able to agree on a work programme.
Шестерка председателей проложила путь к переговорам, которые окажутся необходимыми, когда мы окажемся в состоянии согласовать программу работы.
This is the right path for my people.
Or you could say that it ignores nature and build the path for itself.
Или можно сказать, что противостоит им и строит себе путь для себя.
You probably want to wait here until we can clear a path for you.
Вероятно, вы захотите подождать, пока мы не расчистим путь для вас.
The Protocol charts a political path for all shades of Angolan political opinion.
Протокол определяет политический путь для всего спектра политического мнения в Анголе.
It is felt that neuroscience is a very promising path for the search for the quantified evaluation of art.
Считается, что нейронаука — очень перспективный путь для поиска количественной оценки искусства.
It is the path for very strong people.
Enter the path for the transaction log file.
Введите путь к файлу журнала транзакций.
Clear a path for Mordecai, and stay away from those timelines.
Расчистить путь для Мордекая, и держитесь подальше от временных линий.
Here, we find the most just and appropriate path for cooperation in the development of our nations.
В этом мы находим наиболее справедливый и подходящий путь для сотрудничества в деле развития наших наций.
Objectively, this is not the best path for humankind.
Поистине, это не лучший путь для человечества.
The best path for humankind is for nuclear weapons to disappear altogether.
Лучший путь для человечества — это полная ликвидация ядерного оружия.
The Secretary-General has just shown us the right path for peace, security and disarmament.
Генеральный секретарь только что указал нам надлежащий путь к миру, безопасности и разоружению.
Then there are three strategic directions that chart a path for the IPU over the next five years towards the fulfilment of its vision.
Затем указываются три стратегических направления, намечающие курс МПС к претворению в жизнь его перспективного видения на следующие пять лет.
Africa supported the green economy as a path for development affording opportunities for economic diversification, the creation of decent jobs and combating poverty.
Африка поддерживает «зеленую» экономику в качестве пути развития, который предоставляет возможности для диверсификации экономики, создания достойных рабочих мест и борьбы с нищетой.
It considered the Doha Round to be the best path for addressing such issues.
Делегация считает Дохинский раунд лучшим способом разрешения этих проблем.
The energy initiative could represent a strategic path for the Organization’s future programmatic orientation.
Инициатива в области энергетики, возможно, является одним из стратегических ориентиров для будущих программ Организации.
In that regard, Ecuador had traced out a path for reducing the digital divide within society.
В этой связи Эквадор наметил для себя курс сокращения цифрового разрыва внутри общества.
And the ring… other open the path for you.
И позвоню… на другие станции… чтобы открыть для вас путь.
Почему вам следует использовать pathlib / Хабр
От переводчика: Привет, хабр! Представляю вашему вниманию перевод статьи Why you should be using pathlib и её продолжения, No really, pathlib is great. Много внимания нынче уделяется таким новым возможностям Python, как asyncio, оператору :=, и опциональной типизации. При этом за радаром рискуют пройти не столь значительные (хотя, := назвать серьёзным нововведением язык не поворачивается), но весьма полезные нововведения в язык. В частности, на хабре статей, посвящённых сабжу, я не нашел (кроме одного абзаца тут), поэтому решил исправить ситуацию.
Когда я открыл для себя тогда еще новый модуль pathlib несколько лет назад, я по простоте душевной решил, что это всего лишь слегка неуклюжая объектно-ориентированная версия модуля os.path
. Я ошибался. pathlib
на самом деле чудесен!
В этой статье я попытаюсь вас влюбить в pathlib
. Я надеюсь, что эта статья вдохновит вас использовать pathlib
в любой ситуации, касающейся работы с файлами в Python.
Часть 1.
os.path
неуклюж
Модуль os.path
всегда был тем, что мы использовали когда речь заходила про пути в Python. В принципе, там есть всё, что вам нужно, но часто выглядит это не слишком изящно.
Стоит ли импортировать его так?
import os.path
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')
Или так?
from os.path import abspath, dirname, join
BASE_DIR = dirname(dirname(abspath(__file__)))
TEMPLATES_DIR = join(BASE_DIR, 'templates')
Может быть функция join
имеет слишком общее название, и нам стоит сделать что-то такое:
from os.path import abspath, dirname, join as joinpath
BASE_DIR = dirname(dirname(abspath(__file__)))
TEMPLATES_DIR = joinpath(BASE_DIR, 'templates')
Мне все варианты выше кажутся не слишком удобными. Мы передаём строки в функции, которые возвращают строки, которые мы передаём следующим функциям, работающим со строками. Так уж случилось, что они все содержат пути, но они всё еще всего лишь строки.
Использование строк для ввода и вывода в функциях os.path
весьма неудобное, потому что код приходится читать изнутри наружу. Хотелось бы преобразовать эти вызовы из вложенных в последовательные. Именно это и позволяет сделать pathlib
!
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = BASE_DIR.joinpath('templates')
Модуль os.path
требует вложенных вызовов функций, но pathlib
позволяет нам создавать цепочки последовательных вызовов методов и атрибутов класса Path
с эквивалентным результатом.
Я знаю что вы думаете: стоп, эти объекты Path
— не то же самое, что было раньше, мы больше не оперируем строками путей! К этому вопросу вернёмся позже (подсказка: почти в любой ситуации эти два подхода взаимозаменяемы).
os
перегружен
Классический модуль os.path
предназначен для работы с путями. Но после того как вы что-то хотите сделать с путём (например, создать директорию), вам нужно будет обращаться к другому модулю, часто os
.
os
содержит кучу утилит для работы с файлами и директориями: mkdir
, getcwd
, chmod
, stat
, remove
, rename
, rmdir
. Также chdir
, link
, walk
, listdir
, makedirs
, renames
, removedirs
, unlink
, symlink
. И еще кучу всякой всячины, не связанной с файловыми системами вовсе: fork
, getenv
, putenv
, environ
, getlogin
, system
,… Еще несколько дюжин вещей, о которых я упоминать здесь не буду.
Модуль os
предназначен для широкого круга задач; это такой ящик со всем, связанным с операционной системой. Есть много полезностей в os
, но в нём не всегда легко ориентироваться: часто необходимо слегка покопаться в модуле, прежде чем вы найдёте то, что нужно.
pathlib
переносит большинство функций по работе с файловой системой в объекты Path
.
Вот код, который создаёт директорию src/__pypackages__
и переименовывает наш файл .editorconfig
в src/.editorconfig
:
import os
import os.path
os.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True)
os.rename('.editorconfig', os.path.join('src', '.editorconfig'))
Вот аналогичный код, использующий Path
from pathlib import Path
Path('src/__pypackages__').mkdir(parents=True, exist_ok=True)
Path('.editorconfig').rename('src/.editorconfig')
Заметьте, что второй пример кода гораздо проще читать, потому что он организован слева направо — это всё благодаря цепочкам методов.
Не забывайте про glob
Не только os
и os.path
содержат методы, связанные с файловой системой. Также стоит упомянуть про glob
, который нельзя назвать бесполезным.
Мы можем использовать функцию glob.glob
для поиска файлов по определённому шаблону:
from glob import glob
top_level_csv_files = glob('*.csv')
all_csv_files = glob('**/*.csv', recursive=True)
Модуль pathlib
также предоставляет аналогичные методы:
from pathlib import Path
top_level_csv_files = Path.cwd().glob('*.csv')
all_csv_files = Path.cwd().rglob('*.csv')
После перехода на модуль pathlib
, необходимость в модуле glob
пропадает полностью: всё необходимое уже является составной частью объектов Path
pathlib
делает простые вещи еще проще
pathlib
упрощает многие сложные ситуации, но помимо этого делает некоторые простые фрагменты кода еще проще.
Хотите прочитать весь текст в одном или нескольких файлах?
Можете открыть файл, прочитать содержимое, и закрыть файл, используя блок with
:
from glob import glob
file_contents = []
for filename in glob('**/*.py', recursive=True):
with open(filename) as python_file:
file_contents.append(python_file.read())
Или вы можете использовать метод read_text
на объектах Path
и генерацию списков что бы получить аналогичный результат за одно выражение:
from pathlib import Path
file_contents = [
path.read_text()
for path in Path.cwd().rglob('*.py')
]
А что, если нужно записать в файл?
Вот как это выглядит, используя open
:
with open('.editorconfig') as config:
config.write('# config goes here')
Или же вы можете использовать метод write_text
:
Path('.editorconfig').write_text('# config goes here')
Если по каким-либо причинам вам необходимо использовать open
, либо в качестве контекстного менеджера, либо по личным предпочтениям, Path
предоставляет метод open
, как альтернативу:
from pathlib import Path
path = Path('.editorconfig')
with path.open(mode='wt') as config:
config.write('# config goes here')
Или же, начиная с Python 3.6, можно передать ваш Path
напрямую в open
:
from pathlib import Path
path = Path('.editorconfig')
with open(path, mode='wt') as config:
config.write('# config goes here')
Объекты Path делают ваш код очевиднее
На что указывают следующие переменные? Какой смысл у их значений?
person = '{"name": "Trey Hunner", "location": "San Diego"}'
pycon_2019 = "2019-05-01"
home_directory = '/home/trey'
Каждая переменная указывает на строку. Но каждая из них имеет разные значения: первая — это JSON, вторая — дата, и третья — это файловый путь.
Вот такое представление объектов слегка полезнее:
from datetime import date
from pathlib import Path
person = {"name": "Trey Hunner", "location": "San Diego"}
pycon_2019 = date(2019, 5, 1)
home_directory = Path('/home/trey')
Объекты JSON можно десериализовать в словарь, даты можно нативно представить, используя datetime.date
, а объекты файловых путей можно представить в виде Path
Использование объектов Path
делает ваш код более явным. Если вы хотите работать с датами, вы используете date
. Если хотите работать с файловыми путями, используйте Path
.
Я не особо большой сторонник ООП. Классы добавляют дополнительный слой абстракции, а абстракциям иногда свойственно усложнять систему, а не упрощать. При этом, я считаю, что pathlib.Path
— это полезная абстракция. Довольно быстро она становится общепринятым решением.
Благодаря PEP 519, Path
становятся стандартными для работы с путями. На момент Python 3.6, большинство методов os
, shutil
, os.path
корректно работают с этими объектами. Вы можете уже сегодня перейти на использование pathlib
, прозрачно для вашей кодовой базы!
Чего не хватает в pathlib
?
Хотя pathlib
и классная, но не всеобъемлющаяя. Определённо есть несколько возможностей, которые я бы хотел, что бы были включены в модуль.
Первое, что приходит на ум, это недостаток методов у Path
, эквивалентных shutil
. И хотя вы можете передавать Path
как параметры shutil
для копирования/удаления/перемещения файлов и директорий, вызывать их как методы у объектов Path
не получится.
Так что, для копирования файлов, необходимо сделать что-то вроде этого:
from pathlib import Path
from shutil import copyfile
source = Path('old_file.txt')
destination = Path('new_file.txt')
copyfile(source, destination)
Также нет аналога метода os.chdir
. Это означает, что вам необходимо её импортировать, если возникнет необходимость сменить текущую директорию:
from pathlib import Path
from os import chdir
parent = Path('..')
chdir(parent)
Также нет эквивалента функции os.walk
. Хотя вы можете написать свою собственную функцию в духе walk
без особых сложностей.
Я надеюсь что однажды объекты pathlib.Path
будут содержать методы для некоторых из упомянутых операций. Но даже при таком раскладе я считаю гораздо более простым подход «использовать pathlib
с чем-то еще» чем «использовать os.path
и всё остальное».
Всегда ли нужно использовать pathlib
?
Начиная с Python 3.6, Path работают практически везде, где вы используете строки. Так что я не вижу причин не использовать pathlib
, если вы используете Python 3.6 и выше.
Если же вы используете более раннюю версию Python 3, вы в любой момент можете обернуть объект Path
в вызов str
что бы получить строку, если возникла необходимость вернуться в страну строчек. Это не слишком изящно, но работает:
from os import chdir
from pathlib import Path
chdir(Path('/home/trey')) # Работает в Python 3.6+
chdir(str(Path('/home/trey'))) # Работает в более старых версиях
Часть 2. Ответы на вопросы.
После публикации первой части у некоторых людей возникли некоторые вопросы. Кто-то говорил, что я сравнивал библиотеки os.path
и pathlib
нечестно. Некоторые говорили, что использование os.path
настолько укоренилось в сообществе Python, что переход на новую библиотеку займёт очень большой промежуток времени. Еще я видел некоторые вопросы по поводу производительности.
В этой части я бы хотел прокомментировать эти вопросы. Можно считать это одновременно защитой pathlib
и чем-то вроде любовного письма к PEP 519.
Сравнение os.path
и pathlib
по-честному
В прошлой части я сравнивал следующие два фрагмента кода:
import os
import os.path
os.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True)
os.rename('.editorconfig', os.path.join('src', '.editorconfig'))
from pathlib import Path
Path('src/__pypackages__').mkdir(parents=True, exist_ok=True)
Path('.editorconfig').rename('src/.editorconfig')
Это может показаться нечестным сравнением, потому что использование os.path.join
в первом примере гарантирует использование корректных разделителей на всех платформах, чего я не делал во втором примере. На самом же деле, всё в порядке, потому что Path автоматически нормализует разделители путей
Мы можем доказать это, посмотрев на преобразование объекта Path
в строку на Windows:
>>> str(Path('src/__pypackages__'))
'src\\__pypackages__'
Без разницы — используем ли мы метод joinpath
, '/'
в строке пути, оператор /
(еще одна приятная фишка Path
), или передаём отдельные аргументы в конструктор Path, мы получаем одинаковый результат:
>>> Path('src', '.editorconfig')
WindowsPath('src/.editorconfig')
>>> Path('src') / '.editorconfig'
WindowsPath('src/.editorconfig')
>>> Path('src').joinpath('.editorconfig')
WindowsPath('src/.editorconfig')
>>> Path('src/.editorconfig')
WindowsPath('src/.editorconfig')
Последний пример вызвал некоторое замешательство от людей, которые предполагали, что pathlib
недостаточно умён для замены /
на \
в строке пути. К счастью, всё в порядке!
С объектами Path
, вам больше не нужно беспокоиться по поводу направления слэшей: определяйте все свои пути с использованием /
, и результат будет предсказуем для любой платформы.
Вы не должны беспокоиться о нормализации путей
Если вы работаете на Linux или Mac, очень легко случайно добавить в код баги, которые затронут только пользователей Windows. Если не следить внимательно за использованием os.path.join
и\или os.path.normcase
для конвертации слэшей в подходящие для текущей платформы, вы можете написать код, который не будет корректно работать в Windows.
Вот пример Windows-specific бага:
import sys
import os.path
directory = '.' if not sys.argv[1:] else sys.argv[1]
new_file = os.path.join(directory, 'new_package/__init__.py')
При этом такой код будет работать корректно везде:
import sys
from pathlib import Path
directory = '.' if not sys.argv[1:] else sys.argv[1]
new_file = Path(directory, 'new_package/__init__.py')
Ранее программист был ответственен за конкатенацию и нормализацию путей, точно так же, как в Python 2 программист был ответственен за решение, где стоит использовать unicode вместо bytes. Больше это не ваша задача — все подобные проблемы Path
решает за вас.
Я не использую Windows, и у меня нет компьютера с Windows. Но огромное множество людей, которые будут использовать мой код, очень вероятно будут использовать Windows, и я хочу, что бы у них всё работало корректно.
Если есть вероятность, что ваш код будет запускаться на Windows, вам стоит серьёзно задуматься над переходом на pathlib
.
Не беспокойтесь о нормализации: используйте Path
в любом случае, когда речь заходит о путях к файлам.
Звучит классно, но у меня сторонняя библиотека, которая не использует pathlib
!
У вас большая кодовая база, которая работает со строками в качестве путей. Зачем переходить на pathlib
, если это означает, что всё нужно переписывать?
Давайте представим, что у вас есть следующая функция:
import os
import os.path
def make_editorconfig(dir_path):
"""Create .editorconfig file in given directory and return filename."""
filename = os.path.join(dir_path, '.editorconfig')
if not os.path.exists(filename):
os.makedirs(dir_path, exist_ok=True)
open(filename, mode='wt').write('')
return filename
Функция принимает директорию, и создаёт там файл .editorconfig
, примерно так:
>>> import os.path
>>> make_editorconfig(os.path.join('src', 'my_package'))
'src/my_package/.editorconfig'
Если заменить строки на Path
, всё тоже заработает:
>>> from pathlib import Path
>>> make_editorconfig(Path('src/my_package'))
'src/my_package/.editorconfig'
Но… как?
os.path.join
принимает объекты Path
(начиная с Python 3.6). То же самое можно сказать и про os.makedirs
.
На самом деле, встроенная функция open
принимает Path
, shutil
принимает Path
и всё, что в стандартной библиотеке раньше принимало строку, теперь должно работать как с Path
, так и со строками.
За это стоит благодарить PEP 519, который предоставил абстрактный класс os.PathLike
и объявил, что все встроенные утилиты для работы с путями к файлам теперь должны работать как со строками, так и с Path
.
Но в моей любимой библиотеке есть Path, лучше стандартного!
Возможно, вы уже используете стороннюю библиотеку, которая предоставляет свою реализацию Path
, которая отличается от стандартной. Возможно, она вам нравится больше.
Например, django-environ, path.py, plumbum, и visidata содержат свои собственные объекты Path
. Некоторые из этих библиотек старше pathlib
, и приняли решение наследоваться от str
, что бы их можно было передать в функции, ожидающие строки в качестве путей. Благодаря PEP 519, интеграция сторонних библиотек в ваш код будет проще, и без необходимости для наследования от str
.
Давайте представим, что вы не хотите использовать pathlib
, потому что Path
— иммутабельные объекты, а вам ну прям очень хочется менять их состояние. Благодаря PEP 519 вы можете создать свою самую-лучшую-мутабельную версию Path
. Для этого достаточно реализовать метод __fspath__
Любая самостоятельно написанная реализация Path
теперь может нативно работать с встроенными функциями Python, которые ожидают файловые пути. Даже если вам не нравится pathlib
, сам факт её существования — это большой плюс для сторонних библиотек с собственными Path
Но ведь pathlib.Path
и str
не смешиваются, правда?
Вы возможно думаете: это всё, конечно, здорово, но разве этот подход с иногда-строка-а-иногда-path не добавит ли сложности в мой код?
Ответ на этот вопрос — да, в некоторой степени. Но у этой проблемы есть довольно простой обход.
PEP 519 добавил еще несколько вещей, помимо PathLike
: во-первых, это способ конвертировать любой PathLike
в строку, а во-вторых, это способ любой PathLike
превратить в Path
.
Возьмём два объекта — строку и Path
(или что угодно с методом fspath):
from pathlib import Path
import os.path
p1 = os.path.join('src', 'my_package')
p2 = Path('src/my_package')
Функция os.fspath
нормализирует оба объекта и превратит в строки:
>>> from os import fspath
>>> fspath(p1), fspath(p2)
('src/my_package', 'src/my_package')
При этом, Path
может принять оба эти объекта в конструктор и преобразовать их в Path
:
>>> Path(p1), Path(p2)
(PosixPath('src/my_package'), PosixPath('src/my_package'))
Это означает, что вы можете преобразовать результат make_editorconfig
назад в Path
при необходимости:
>>> from pathlib import Path
>>> Path(make_editorconfig(Path('src/my_package')))
PosixPath('src/my_package/.editorconfig')
Хотя, конечно, лучшим решением было бы переписать make_editorconfig
, используя pathlib
.
pathlib
слишком медленный
Я видел несколько раз вопросы по поводу производительности pathlib
. Это правда — pathlib
может быть медленным. Создание тысяч объектов Path
может заметно сказаться на поведении программы.
Я решил замерить производительность pathlib
и os.path
на своём компьютере, используя две разные программы, которые ищут все .py
файлы в текущей директории
Вот версия os.walk
:
from os import getcwd, walk
extension = '.py'
count = 0
for root, directories, filenames in walk(getcwd()):
for filename in filenames:
if filename.endswith(extension):
count += 1
print(f"{count} Python files found")
А вот версия с Path.rglob
:
from pathlib import Path
extension = '.py'
count = 0
for filename in Path.cwd().rglob(f'*{extension}'):
count += 1
print(f"{count} Python files found")
Тестирование производительности программ, которые работают с файловой системой — задача хитрая, потому что время работы может меняться довольно сильно. Я решил запустить каждый скрипт 10 раз и сравнил лучшие результаты для каждой программы.
Обе программы нашли 97507 файла в директории, в которой я их запускал. Первый сработал за 1.914 секунды, второй закончил работу за 3.430 секунды.
Когда я установил параметр extension=''
, эти программы находят примерно 600,000 файлов, и разница увеличивается. Первая программа сработала за 1.888 секунд, а вторая за 7.485 секунд.
Так что, pathlib
работает примерно вдвое медленнее для файлов с расширением .py
, и в четыре раза медленнее при запуске на моей домашней директории. Относительный разрыв в производительности pathlib
и os
весьма велик.
В моём случае, эта скорость мало что меняет. Я искал все файлы в своей директории и потерял 6 секунд. Если бы у меня была задача обработать 10 миллионов файлов, я бы скорее всего её переписал. Но пока такой необходимости нет, можно и подождать.
Если у вас есть горячий фрагмент кода, и pathlib
явно негативно влияет на его работу, нет ничего плохого в том, что бы заменить его на альтернативу. Не стоит оптимизировать код, который не является узким местом — это лишняя трата времени, которая к тому же обычно приводит к плохо читаемому коду, без особого выхлопа.
Улучшение читаемости
Я хотел бы закончить этот поток мыслей некоторыми примерами рефакторинга при помощи pathlib
. Я взял пару небольших примеров кода, который работает с файлами и заставил их работать с pathlib
. Оставлю большую часть кода без комментариев на ваш суд — решайте, какая версия вам нравится больше.
Вот функция make_editorconfig
, которую мы видели ранее:
import os
import os.path
def make_editorconfig(dir_path):
"""Create .editorconfig file in given directory and return filename."""
filename = os.path.join(dir_path, '.editorconfig')
if not os.path.exists(filename):
os.makedirs(dir_path, exist_ok=True)
open(filename, mode='wt').write('')
return filename
А вот версия, переписанная на pathlib
:
from pathlib import Path
def make_editorconfig(dir_path):
"""Create .editorconfig file in given directory and return filepath."""
path = Path(dir_path, '.editorconfig')
if not path.exists():
path.parent.mkdir(exist_ok=True, parent=True)
path.touch()
return path
Вот консольная программа которая принимает строку с директорией и печатает содержимое файла .gitignore
, если он существует:
import os.path
import sys
directory = sys.argv[1]
ignore_filename = os.path.join(directory, '.gitignore')
if os.path.isfile(ignore_filename):
with open(ignore_filename, mode='rt') as ignore_file:
print(ignore_file.read(), end='')
То же самое, но с pathlib
:
from pathlib import Path
import sys
directory = Path(sys.argv[1])
ignore_path = directory / '.gitignore'
if ignore_path.is_file():
print(ignore_path.read_text(), end='')
Вот программа, которая печатает все дублирующиеся файлы в текущей папке и подпапках:
from collections import defaultdict
from hashlib import md5
from os import getcwd, walk
import os.path
def find_files(filepath):
for root, directories, filenames in walk(filepath):
for filename in filenames:
yield os.path.join(root, filename)
file_hashes = defaultdict(list)
for path in find_files(getcwd()):
with open(path, mode='rb') as my_file:
file_hash = md5(my_file.read()).hexdigest()
file_hashes[file_hash].append(path)
for paths in file_hashes.values():
if len(paths) > 1:
print("Duplicate files found:")
print(*paths, sep='\n')
То же самое, но c pathlib
:
from collections import defaultdict
from hashlib import md5
from pathlib import Path
def find_files(filepath):
for path in Path(filepath).rglob('*'):
if path.is_file():
yield path
file_hashes = defaultdict(list)
for path in find_files(Path.cwd()):
file_hash = md5(path.read_bytes()).hexdigest()
file_hashes[file_hash].append(path)
for paths in file_hashes.values():
if len(paths) > 1:
print("Duplicate files found:")
print(*paths, sep='\n')
Изменения незначительные, но, по-моему, в сумме дают положительный результат. Я лично предпочитаю варианты с использованием pathlib
.
Начните использовать объекты pathlib.Path
Давайте повторим.
Разделители /
в строках pathlib.Path
автоматически конвертируются в правильный разделитель для текущей операционной системы. Это важная особенность, которая делает код более читаемым и избавляет от потенциальных багов.
>>> path2 = Path('dir', 'file')
>>> path3 = Path('dir') / 'file'
>>> path4 = Path('dir/file')
>>> path4
WindowsPath('dir/file')
>>> path2 == path3 == path4
True
Встроенные в Python функции (напр. open
) также принимают Path
, что значит, что вы можете использовать pathlib
, даже если ваши сторонние библиотеки этого не делают!
from shutil import move
def rename_and_redirect(old_filename, new_filename):
move(old, new)
with open(old, mode='wt') as f:
f.write(f'This file has moved to {new}')
>>> from pathlib import Path
>>> old, new = Path('old.txt'), Path('new.txt')
>>> rename_and_redirect(old, new)
>>> old.read_text()
'This file has moved to new.txt'
И если вам не нравится pathlib
, вы можете использовать стороннюю библиотеку, которая реализует интерфейс PathLike
. Это отлично, потому что даже если вам не нравится стандартная реализация, вы всё равно получите выгоду от изменений, принятых в PEP 519.
>>> from plumbum import Path
>>> my_path = Path('old.txt')
>>> with open(my_path) as f:
... print(f.read())
...
This file has moved to new.txt
И хотя pathlib
может быть медленнее альтернатив, обычно это не так важно (по крайней мере, мой опыт показывает так), к тому же вы всегда можете вернуться к использованию строк для фрагментов кода, чувствительных к производительности.
В целом, pathlib
позволяет писать более читаемый код. Вот короткий и ёмкий скрипт на Python для иллюстрации моей точки зрения:
from pathlib import Path
gitignore = Path('.gitignore')
if gitignore.is_file():
print(gitignore.read_text(), end='')
Модуль pathlib
— отличный. Начните же его использовать!
path — Перевод на русский — примеры английский
Предложения:
career path
growth path
На основании Вашего запроса эти примеры могут содержать грубую лексику.
На основании Вашего запроса эти примеры могут содержать разговорную лексику.
This Global Action Agenda charts a path forward for the initiative and its stakeholders.
В этой Глобальной программе действий определен путь продвижения вперед в рамках данной инициативы, которым должны следовать и задействованные в ней заинтересованные стороны.
And I hope someday, that path earns me your forgiveness.
И я надеюсь, что однажды, этот путь позволит заслужить твоё прощение.
Those examples show the path to follow.
Эти примеры указывают направление, в котором нужно двигаться.
He therefore urged Slovakia to pursue that path.
В этой связи докладчик призывает Словакию продолжать свою деятельность в этом направлении.
Yan-ru eventually underwent surgery and is now on the path to recovery.
В итоге Яньжу была сделана операция, и сейчас она находится на пути к выздоровлению.
We advanced, slaughtering every rebel who crossed our path.
Мы продвигались, убивая каждого мятежника, который вставал на нашем пути.
Trav chose this path because he loves it.
Тревис выбрал этот путь потому, что он любит это.
That uphill path the wind travels…
Тот путь вверх по склону, которым путешествует ветер.
Greater support is the shortest path towards independence.
Предоставление более существенной поддержки — это кратчайший путь к обретению независимости.
Therefore, the longest path problem is NP-hard.
Таким образом, задача поиска самого длинного пути является NP-трудной.
Each path of development contains unique units and possibilities.
Какой бы путь развития ни был выбран, на нём будут доступны уникальные юниты и возможности.
Unfortunately, Judy chose that path.
К сожалению, Джуди сама выбрала этот путь».
This would open the path to full self-realization.
Это будет означать, что открывается путь к полной самореализации.
Added path storing of the previously opened backup file.
Добавлено запоминание и отображение пути к папке с файлами архивных копий.
Its signal is damaging everything in its path.
Зонд движется к нам, повреждая все на своем пути.
You chose this path: follow it.
Вы избрали свой путь, следуйте же по нему.
You know your path, child.
Ты знаешь, где твой путь, дитя.
However, a variety of obstacles lie in his path.
Но, как оказывается, на его пути начинают возникать различные препятствия.
A decade later, Lafortune suggested many refinements, including bidirectional path tracing.
Позже в этом году Лафортюн (англ. Lafortune) предложил много усовершенствований алгоритма, в том числе путём двунаправленной трассировки пути.
The object with package path does not provide configurable properties.
Объект, расположенный по следующему пути к пакету, не имеет настраиваемых свойств.
работа с файловой системой / RUVDS.com corporate blog / Habr
Сегодня, в девятой части перевода руководства по Node.js, мы поговорим о работе с файлами. В частности, речь пойдёт о модулях fs и path — о файловых дескрипторах, о путях к файлам, о получении информации о файлах, об их чтении и записи, о работе с директориями.
[Советуем почитать] Другие части циклаЧасть 1: Общие сведения и начало работы
Часть 2: JavaScript, V8, некоторые приёмы разработки
Часть 3: Хостинг, REPL, работа с консолью, модули
Часть 4: npm, файлы package.json и package-lock.json
Часть 5: npm и npx
Часть 6: цикл событий, стек вызовов, таймеры
Часть 7: асинхронное программирование
Часть 8: Руководство по Node.js, часть 8: протоколы HTTP и WebSocket
Часть 9: Руководство по Node.js, часть 9: работа с файловой системой
Часть 10: Руководство по Node.js, часть 10: стандартные модули, потоки, базы данных, NODE_ENV
Полная PDF-версия руководства по Node.js
Работа с файловыми дескрипторами в Node.js
Прежде чем вы сможете взаимодействовать с файлами, находящимися в файловой системе вашего сервера, вам необходимо получить дескриптор файла.
Дескриптор можно получить, воспользовавшись для открытия файла асинхронным методом open()
из модуля fs
:
const fs = require('fs')
fs.open('/Users/flavio/test.txt', 'r', (err, fd) => {
//fd - это дескриптор файла
})
Обратите внимание на второй параметр, r
, использованный при вызове метода fs.open()
. Это — флаг, который сообщает системе о том, что файл открывают для чтения. Вот ещё некоторые флаги, которые часто используются при работе с этим и некоторыми другими методами:
r+
— открыть файл для чтения и для записи.w+
— открыть файл для чтения и для записи, установив указатель потока в начало файла. Если файл не существует — он создаётся.a
— открыть файл для записи, установив указатель потока в конец файла. Если файл не существует — он создаётся.a+
— открыть файл для чтения и записи, установив указатель потока в конец файла. Если файл не существует — он создаётся.
Файлы можно открывать и пользуясь синхронным методом fs.openSync()
, который, вместо того, чтобы предоставить дескриптор файла в коллбэке, возвращает его:
const fs = require('fs')
try {
const fd = fs.openSync('/Users/flavio/test.txt', 'r')
} catch (err) {
console.error(err)
}
После получения дескриптора любым из вышеописанных способов вы можете производить с ним необходимые операции.
Данные о файлах
С каждым файлом связан набор данных о нём, исследовать эти данные можно средствами Node.js. В частности, сделать это можно, используя метод stat()
из модуля fs
.
Вызывают этот метод, передавая ему путь к файлу, и, после того, как Node.js получит необходимые сведения о файле, он вызовет коллбэк, переданный методу stat()
. Вот как это выглядит:
const fs = require('fs')
fs.stat('/Users/flavio/test.txt', (err, stats) => {
if (err) {
console.error(err)
return
}
//сведения о файле содержатся в аргументе `stats`
})
В Node.js имеется возможность синхронного получения сведений о файлах. При таком подходе главный поток блокируется до получения свойств файла:
const fs = require('fs')
try {
const stats = fs.statSync ('/Users/flavio/test.txt')
} catch (err) {
console.error(err)
}
Информация о файле попадёт в константу stats
. Что это за информация? На самом деле, соответствующий объект предоставляет нам большое количество полезных свойств и методов:
- Методы
.isFile()
и.isDirectory()
позволяют, соответственно, узнать, является ли исследуемый файл обычным файлом или директорией. - Метод
.isSymbolicLink()
позволяет узнать, является ли файл символической ссылкой. - Размер файла можно узнать, воспользовавшись свойством
.size
.
Тут имеются и другие методы, но эти — самые употребимые. Вот как ими пользоваться:
const fs = require('fs')
fs.stat('/Users/flavio/test.txt', (err, stats) => {
if (err) {
console.error(err)
return
}
stats.isFile() //true
stats.isDirectory() //false
stats.isSymbolicLink() //false
stats.size //1024000 //= 1MB
})
Пути к файлам в Node.js и модуль path
Путь к файлу — это адрес того места в файловой системе, где он расположен.
В Linux и macOS путь может выглядеть так:
/users/flavio/file.txt
В Windows пути выглядят немного иначе:
C:\users\flavio\file.txt
На различия в форматах записи путей при использовании разных операционных систем следует обращать внимание, учитывая операционную систему, используемую для развёртывания Node.js-сервера.
В Node.js есть стандартный модуль path
, предназначенный для работы с путями к файлам. Перед использованием этого модуля в программе его надо подключить:
const path = require('path')
▍Получение информации о пути к файлу
Если у вас есть путь к файлу, то, используя возможности модуля path
, вы можете, в удобном для восприятия и дальнейшей обработки виде, узнать подробности об этом пути. Выглядит это так:
const notes = '/users/flavio/notes.txt'
path.dirname(notes) // /users/flavio
path.basename(notes) // notes.txt
path.extname(notes) // .txt
Здесь, в строке notes
, хранится путь к файлу. Для разбора пути использованы следующие методы модуля path
:
dirname()
— возвращает родительскую директорию файла.basename()
— возвращает имя файла.extname()
— возвращает расширение файла.
Узнать имя файла без расширения можно, вызвав метод .basename()
и передав ему второй аргумент, представляющий расширение:
path.basename(notes, path.extname(notes)) //notes
▍Работа с путями к файлам
Несколько частей пути можно объединить, используя метод path.join()
:
const name = 'flavio'
path.join('/', 'users', name, 'notes.txt') //'/users/flavio/notes.txt'
Найти абсолютный путь к файлу на основе относительного пути к нему можно с использованием метода path.resolve()
:
path.resolve('flavio.txt')
//'/Users/flavio/flavio.txt' при запуске из моей домашней папки
В данном случае Node.js просто добавляет /flavio.txt
к пути, ведущем к текущей рабочей директории. Если при вызове этого метода передать ещё один параметр, представляющий путь к папке, метод использует его в качестве базы для определения абсолютного пути:
path.resolve('tmp', 'flavio.txt')
// '/Users/flavio/tmp/flavio.txt' при запуске из моей домашней папки
Если путь, переданный в качестве первого параметра, начинается с косой черты — это означает, что он представляет собой абсолютный путь.
path.resolve('/etc', 'flavio.txt')
// '/etc/flavio.txt'
Вот ещё один полезный метод — path.normalize()
. Он позволяет найти реальный путь к файлу, используя путь, в котором содержатся спецификаторы относительного пути вроде точки (.
), двух точек (..
), или двух косых черт:
path.normalize('/users/flavio/..//test.txt')
// /users/test.txt
Методы resolve()
и normalize()
не проверяют существование директории. Они просто находят путь, основываясь на переданным им данным.
Чтение файлов в Node.js
Самый простой способ чтения файлов в Node.js заключается в использовании метода fs.readFile()
с передачей ему пути к файлу и коллбэка, который будет вызван с передачей ему данных файла (или объекта ошибки):
fs.readFile('/Users/flavio/test.txt', (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
})
Если надо, можно воспользоваться синхронной версией этого метода — fs.readFileSync()
:
const fs = require('fs')
try {
const data = fs.readFileSync('/Users/flavio/test.txt')
console.log(data)
} catch (err) {
console.error(err)
}
По умолчанию при чтении файлов используется кодировка utf8
, но кодировку можно задать и самостоятельно, передав методу соответствующий параметр.
Методы fs.readFile()
и fs.readFileSync()
считывают в память всё содержимое файла. Это означает, что работа с большими файлами с применением этих методов серьёзно отразится на потреблении памяти вашим приложением и окажет влияние на его производительность. Если с такими файлами нужно работать, лучше всего воспользоваться потоками.
Запись файлов в Node.js
В Node.js легче всего записывать файлы с использованием метода fs.writeFile()
:
const fs = require('fs')
const content = 'Some content!'
fs.writeFile('/Users/flavio/test.txt', content, (err) => {
if (err) {
console.error(err)
return
}
//файл записан успешно
})
Есть и синхронная версия того же метода — fs.writeFileSync()
:
const fs = require('fs')
const content = 'Some content!'
try {
const data = fs.writeFileSync('/Users/flavio/test.txt', content)
//файл записан успешно
} catch (err) {
console.error(err)
}
Эти методы, по умолчанию, заменяют содержимое существующих файлов. Изменить их стандартное поведение можно, воспользовавшись соответствующим флагом:
fs.writeFile('/Users/flavio/test.txt', content, { flag: 'a+' }, (err) => {})
Тут могут использоваться флаги, которые мы уже перечисляли в разделе, посвящённом дескрипторам. Подробности о флагах можно узнать здесь.
Присоединение данных к файлу
Метод fs.appendFile()
(и его синхронную версию — fs.appendFileSync()
) удобно использовать для присоединения данных к концу файла:
const content = 'Some content!'
fs.appendFile('file.log', content, (err) => {
if (err) {
console.error(err)
return
}
//готово!
})
Об использовании потоков
Выше мы описывали методы, которые, выполняя запись в файл, пишут в него весь объём переданных им данных, после чего, если используются их синхронные версии, возвращают управление программе, а если применяются асинхронные версии — вызывают коллбэки. Если вас такое состояние дел не устраивает — лучше будет воспользоваться потоками.
Работа с директориями в Node.js
Модуль fs
предоставляет в распоряжение разработчика много удобных методов, которые можно использовать для работы с директориями.
▍Проверка существования папки
Для того чтобы проверить, существует ли директория и может ли Node.js получить к ней доступ, учитывая разрешения, можно использовать метод fs.access()
.
▍Создание новой папки
Для того чтобы создавать новые папки, можно воспользоваться методами fs.mkdir()
и fs.mkdirSync()
:
const fs = require('fs')
const folderName = '/Users/flavio/test'
try {
if (!fs.existsSync(dir)){
fs.mkdirSync(dir)
}
} catch (err) {
console.error(err)
}
▍Чтение содержимого папки
Для того чтобы прочесть содержимое папки, можно воспользоваться методами fs.readdir()
и fs.readdirSync()
. В этом примере осуществляется чтение содержимого папки — то есть — сведений о том, какие файлы и поддиректории в ней имеются, и возврат их относительных путей:
const fs = require('fs')
const path = require('path')
const folderPath = '/Users/flavio'
fs.readdirSync(folderPath)
Вот так можно получить полный путь к файлу:
fs.readdirSync(folderPath).map(fileName => {
return path.join(folderPath, fileName)
}
Результаты можно отфильтровать для того, чтобы получить только файлы и исключить из вывода директории:
const isFile = fileName => {
return fs.lstatSync(fileName).isFile()
}
fs.readdirSync(folderPath).map(fileName => {
return path.join(folderPath, fileName)).filter(isFile)
}
▍Переименование папки
Для переименования папки можно воспользоваться методами fs.rename()
и fs.renameSync()
. Первый параметр — это текущий путь к папке, второй — новый:
const fs = require('fs')
fs.rename('/Users/flavio', '/Users/roger', (err) => {
if (err) {
console.error(err)
return
}
//готово
})
Переименовать папку можно и с помощью синхронного метода fs.renameSync()
:
const fs = require('fs')
try {
fs.renameSync('/Users/flavio', '/Users/roger')
} catch (err) {
console.error(err)
}
▍Удаление папки
Для того чтобы удалить папку, можно воспользоваться методами fs.rmdir()
или fs.rmdirSync()
. Надо отметить, что удаление папки, в которой что-то есть, задача несколько более сложная, чем удаление пустой папки. Если вам нужно удалять такие папки, воспользуйтесь пакетом fs-extra, который весьма популярен и хорошо поддерживается. Он представляет собой замену модуля fs
, расширяющую его возможности.
Метод remove()
из пакета fs-extra
умеет удалять папки, в которых уже что-то есть.
Установить этот модуль можно так:
npm install fs-extra
Вот пример его использования:
const fs = require('fs-extra')
const folder = '/Users/flavio'
fs.remove(folder, err => {
console.error(err)
})
Его методами можно пользоваться в виде промисов:
fs.remove(folder).then(() => {
//готово
}).catch(err => {
console.error(err)
})
Допустимо и применение конструкции async/await:
async function removeFolder(folder) {
try {
await fs.remove(folder)
//готово
} catch (err) {
console.error(err)
}
}
const folder = '/Users/flavio'
removeFolder(folder)
Модуль fs
Выше мы уже сталкивались с некоторыми методами модуля fs
, применяемыми при работе с файловой системой. На самом деле, он содержит ещё много полезного. Напомним, что он не нуждается в установке, для того, чтобы воспользоваться им в программе, его достаточно подключить:
const fs = require('fs')
После этого у вас будет доступ к его методам, среди которых отметим следующие, некоторые из которых вам уже знакомы:
fs.access()
: проверяет существование файла и возможность доступа к нему с учётом разрешений.fs.appendFile()
: присоединяет данные к файлу. Если файл не существует — он будет создан.fs.chmod()
: изменяет разрешения для заданного файла. Похожие методы:fs.lchmod()
,fs.fchmod()
.fs.chown()
: изменяет владельца и группу для заданного файла. Похожие методы:fs.fchown()
,fs.lchown()
.fs.close()
: закрывает дескриптор файла.fs.copyFile()
: копирует файл.fs.createReadStream()
: создаёт поток чтения файла.fs.createWriteStream()
: создаёт поток записи файла.fs.link()
: создаёт новую жёсткую ссылку на файл.fs.mkdir()
: создаёт новую директорию.fs.mkdtemp()
: создаёт временную директорию.fs.open()
: открывает файл.fs.readdir()
: читает содержимое директории.fs.readFile()
: считывает содержимое файла. Похожий метод:fs.read()
.fs.readlink()
: считывает значение символической ссылки.fs.realpath()
: разрешает относительный путь к файлу, построенный с использованием символов.
и..
, в полный путь.fs.rename()
: переименовывает файл или папку.fs.rmdir()
: удаляет папку.fs.stat()
: возвращает сведения о файле. Похожие методы:fs.fstat()
,fs.lstat()
.fs.symlink()
: создаёт новую символическую ссылку на файл.fs.truncate()
: обрезает файл до заданной длины. Похожий метод:fs.ftruncate()
.fs.unlink()
: удаляет файл или символическую ссылку.fs.unwatchFile()
: отключает наблюдение за изменениями файла.fs.utimes()
: изменяет временную отметку файла. Похожий метод:fs.futimes()
.fs.watchFile()
: включает наблюдение за изменениями файла. Похожий метод:fs.watch()
.fs.writeFile()
: записывает данные в файл. Похожий метод:fs.write()
.
Интересной особенностью модуля fs
является тот факт, что все его методы, по умолчанию, являются асинхронными, но существуют и их синхронные версии, имена которых получаются путём добавления слова Sync
к именам асинхронных методов.
Например:
fs.rename()
fs.renameSync()
fs.write()
fs.writeSync()
Использование синхронных методов серьёзно влияет на то, как работает программа.
В Node.js 10 имеется экспериментальная поддержка этих API, основанных на промисах.
Исследуем метод fs.rename()
. Вот асинхронная версия этого метода, использующая коллбэки:
const fs = require('fs')
fs.rename('before.json', 'after.json', (err) => {
if (err) {
return console.error(err)
}
//готово
})
При использовании его синхронной версии для обработки ошибок используется конструкция try/catch
:
const fs = require('fs')
try {
fs.renameSync('before.json', 'after.json')
//готово
} catch (err) {
console.error(err)
}
Основное различие между этими вариантами использования данного метода заключается в том, что во втором случае выполнение скрипта будет заблокировано до завершения файловой операции.
Модуль path
Модуль path, о некоторых возможностях которого мы тоже уже говорили, содержит множество полезных инструментов, позволяющих взаимодействовать с файловой системой. Как уже было сказано, устанавливать его не нужно, так как он является частью Node.js. Для того чтобы пользоваться им, его достаточно подключить:
const path = require('path')
Свойство path.sep
этого модуля предоставляет символ, использующийся для разделения сегментов пути (\
в Windows и /
в Linux и macOS), а свойство path.delimiter
даёт символ, используемый для отделения друг от друга нескольких путей (;
в Windows и :
в Linux и macOS).
Рассмотрим и проиллюстрируем примерами некоторые методы модуля path
.
▍path.basename()
Возвращает последний фрагмент пути. Передав второй параметр этому методу можно убрать расширение файла.
require('path').basename('/test/something') //something
require('path').basename('/test/something.txt') //something.txt
require('path').basename('/test/something.txt', '.txt') //something
▍path.dirname()
Возвращает ту часть пути, которая представляет имя директории:
require('path').dirname('/test/something') // /test
require('path').dirname('/test/something/file.txt') // /test/something
▍path.extname()
Возвращает ту часть пути, которая представляет расширение файла:
require('path').extname('/test/something') // ''
require('path').extname('/test/something/file.txt') // '.txt'
▍path.isAbsolute()
Возвращает истинное значение если путь является абсолютным:
require('path').isAbsolute('/test/something') // true
require('path').isAbsolute('./test/something') // false
▍path.join()
Соединяет несколько частей пути:
const name = 'flavio'
require('path').join('/', 'users', name, 'notes.txt') //'/users/flavio/notes.txt'
▍path.normalize()
Пытается выяснить реальный путь на основе пути, который содержит символы, использующиеся при построении относительных путей вроде .
, ..
и //
:
require('path').normalize('/users/flavio/..//test.txt') ///users/test.txt
▍path.parse()
Преобразует путь в объект, свойства которого представляют отдельные части пути:
root
: корневая директория.dir
: путь к файлу, начиная от корневой директорииbase
: имя файла и расширение.name
: имя файла.ext
: расширение файла.
Вот пример использования этого метода:
require('path').parse('/users/test.txt')
В результате его работы получается такой объект:
{
root: '/',
dir: '/users',
base: 'test.txt',
ext: '.txt',
name: 'test'
}
▍path.relative()
Принимает, в качестве аргументов, 2 пути. Возвращает относительный путь из первого пути ко второму, основываясь на текущей рабочей директории:
require('path').relative('/Users/flavio', '/Users/flavio/test.txt') //'test.txt'
require('path').relative('/Users/flavio', '/Users/flavio/something/test.txt') //'something/test.txt'
▍path.resolve()
Находит абсолютный путь на основе переданного ему относительного пути:
path.resolve('flavio.txt')
//'/Users/flavio/flavio.txt' при запуске из моей домашней папки.
Итоги
Сегодня мы рассмотрели модули Node.js fs
и path
, которые используются для работы с файловой системой. В следующей части этой серии, на которой она завершается, мы обсудим модули os
, events
, http
, поговорим о работе с потоками и с системами управления базами данных в Node.js.
Уважаемые читатели! Какими npm-пакетами вы пользуетесь при работе с файловой системой в Node.js?
примеры с кодом на Python
В прошлой статье мы говорили об использовании модуля os для работы с каталогами в Python. Сегодня пойдёт речь о высокоуровневом Python-модуле pathlib. Читайте далее, чем отличаются os и pathlib, как управление путями зависит от операционной системы, а также что представляет собой работа с папками и файлами с помощью pathlib.
Иерархия pathlib
Архитектура pathlib состоит из чистых путей (pure path), которые имеют только вычислительные операции, но не имеют операций ввода-вывода, и конкретных путей (concrete path), которые наследуются от чистых путей, но также обладают операциями ввода-вывода. Рисунок ниже показывает иерархию наследования. Как можно заметить, левая часть (Posix Path) используется Unix-системами, а правая – MS Windows.
Иерархия наследования Path
Если вы не знаете какой класс использовать, выбирайте Path. Его экземпляры будут подстраиваться под операционную систему (ОС), и во время выполнения вы получите конкретные экземпляры либо PosixPath, либо WindowsPath.
Чистые пути будут полезны в следующих случаях:
- Требуется управлять каталогами Windows в Unix-системах или наоборот. У вас не получится создать экземпляр WindowsPath в Unix, но можно воспользоваться PureWindowsPath.
- Требуется только управлять путями, не обращаясь к ОС. В этом случае создание экземпляра одного из чистых классов может быть полезным, поскольку у них просто нет операций доступа к ОС.
В дальнейшем мы покажем, как те же самые операции pathlib выполняются в модуле os. Так, pathlib предоставляет высокоуровневый интерфейс, а os — низкоуровенный, поэтому чаще возвращаемым значением является строка (str), а не объекты Path. Прежде чем приступим, импортируем модули в Python:
>>> from pathlib import Path >>> import os
Текущая рабочая директория
Как мы уже говорили в прошлый раз файловая система и Python работают относительно текущей рабочей директории (current working directory). В pathlib для этого имеет метод cwd:
>>> os.getcwd() '/home/user/Templates' >>> pathlib.Path.cwd() PosixPath('/home/user/Templates')
Ещё более короткий и удобный синтаксис вызова текущей директории – это передача в конструктор точку, а две точки укажут на родителя текущей директории:
>>> Path('.') PosixPath('.') # текущая - '/home/user/Templates' >>> Path('..') PosixPath('..') # родитель - '/home/user/'
Создание путей
Разделитель используется для разделения папок в путях файловой системы. В os-модуле его можно посмотреть, вызвав os.sep
. Но здесь возникают трудности, поскольку путь нужно сначала инициализировать в виде строки (str). А если вы забыли, что в Windows используется обратный слэш для деления папок вместо прямого, то код в этом месте придётся менять после вывода ошибки в Python-программе.
С другой стороны, интерфейс Python-модуля pathlib заставляет передавать путь в конструктор объекта Path, который уже сам решит во время выполнения, каким разделителем пользоваться:
>>> os.sep '/' >>> os.path.join('testfolder', 'sub-dir', 'example.txt') 'testfolder/sub-dir/example.txt' >> Path('testfolder', 'sub-dir', 'example.txt') PosixPath('testfolder/sub-dir/example.txt') >>> p = Path('testfolder/sub-dir')
Чтобы добавить новые пути можно использовать слэш /, подобно арифметическому оператору, либо вызвать метод joinpath
, причём соединять также можно и сами объекты Path:
>>> Path('.') / 'tempdir' / 'example.txt' PosixPath('/home/user/Templates/tempdir/example.txt') >>> p = Path('tempdir/examples.txt') >>> Path.('.') / p PosixPath('/home/user/Templates/tempdir/examples.txt') # либо joinpath >>> Path.('.').joinpath('tempdir', 'example.txt') PosixPath('/home/user/Templates/tempdir/example.txt')
Информация о каталоге
В pathlib можно получить информацию о файле или папке, обращаясь к тем или иным атрибутам. Например, name
для извлечения имени файла и его расширения, suffix
для извлечения расширения файла. В Python это выглядит следующим образом:
# Информация о файле >>> p = Path('tempdir/sub-dir/examples.txt') >>> p.name 'examples.txt' # Расширение файла >>> p.suffix '.txt' # То же самое в os: >>> os.path.basename(p) 'examples.txt' >>> os.path.splitext(p)[1] '.txt'
Гуляем по каталогу
У Path есть метод iterdir
, который сгенерирует все папки и файлы указанного пути. Это очень полезно, когда, например, требуется выявить все файлы необходимого формата. Вот так в Python можно найти все текстовые файлы:
>>> p = Path('.') >>> for file in p.iterdir(): ... if file.suffix == '.txt': ... print(file.name) ... example.txt example2.txt
Ещё проще это можно сделать, используя метод glob
, передав нужное расширение:
>>> for path in p.glob('*.txt'): ... print(path) ... example.txt example2.txt
Чтобы пройтись также и по подпапкам в каталоге, можно воспользоваться методом rglob
. В os для этого используется функция walk
, о котором говорили тут. Ниже пример Python для вывода всех путей каталога, а также вывод файлов текстового формата всего каталога:
>>> p = Path('.') >>> list(p.rglob('*')) [PosixPath('example.txt'), PosixPath('sub-dir1'), PosixPath('example2.txt'), PosixPath('sub-dir2'), PosixPath('sub-dir2/example3.txt')] >>> list(p.rglob('*.txt')) [PosixPath('/home/user/Templates/example.txt') PosixPath('/home/user/Templates/example2.txt'), PosixPath('/home/user/Templates/sub-dir2/example3.txt')]
Работа с папками и файлами
Как и os, модуль pathlib даёт возможность создавать, удалять, переименовывать файлы и папки. Причём названия методов практически идентичные:
>>> Path('new-dir').mkdir() # создать папку >>> Path('new-file').touch() # создать файл >>> Path('super-dir').rmdir() # удалить папку >>> Path('example.txt').unlink() # удалить файл >>> Path('new-dir').rename('super-dir') # переименовать файл или папку PosixPath('super-dir')
Кроме того, содержимое файла Path можно прочитать и записать. Ниже показан пример с записью и последующим чтением файла в Python.
>>> p = Path('exapmle.txt') >>> p.write_text('Hello, python-school') >>> p.read_text() 'Hello, python-school'
os или pathlib: что же всё-таки выбрать
После расcмотрения примеров возникает вопрос: каким Python-модулем пользоваться. Модуль os, помимо прочего, предоставляет множество функций для работы с процессами, пользователями, группами, окружением среды в Unix-системах. Но если вам требуется только интерфейс взаимодействия с файловой системой, стоит использовать pathlib, который будет отталкиваться от вашей ОС. При этом вам не потребуется помнить какой используется разделить в Windows или Unix-системах. Модуль pathlib прост в освоении, поскольку имеет простой синтаксис: нужно просто инициализировать объект Path, а дальше смотреть доступные методы. Кроме того, как уже говорилось в самом начале, многие функции os поддерживают объект Path в качестве аргумента, поэтому можно будет перейти от os к pathlib.
Еще больше подробностей о работе с файловой системой с помощью модуля pathlib на практических примерах реальных Data Science проектов вы узнаете на наших курсах по Python в лицензированном учебном центре обучения и повышения квалификации IT-специалистов в Москве.
Источники
- https://docs.python.org/3/library/pathlib.html
path for — Перевод на русский — примеры английский
На основании вашего запроса эти примеры могут содержать грубую лексику.
На основании вашего запроса эти примеры могут содержать разговорную лексику.
Вы не очистили путь для тела .
P6 предоставила путь для переговоров по , которые станут необходимыми, когда мы сможем согласовать программу работы.
Шестерка председателей проложила к переговорам, которые могут быть согласованы, когда мы можем согласовать программу работы.
Это правильный путь для моих людей.
Или вы можете сказать, что он игнорирует природу и построить путь для самого .
Или можно сказать, что противостоит им и строит себе путь для себя.
Вы, вероятно, захотите подождать здесь, пока мы не очистим путь для вас .
Вероятно, вы захотите подождать, пока мы не расчистим путь для вас.
Протокол определяет политический путь для всех оттенков ангольских политических взглядов.
Протокол определяет политический путь для всего качества мнения в Анголе.
Считается, что нейробиология — очень многообещающий путь для поиска количественной оценки искусства.
Считается, что нейронаука — очень перспективный путь для поиска количественного качества искусства.
Это путь для очень сильных людей.
Введите путь для файла журнала транзакций.
Введите путь к файлу журнала транзакций.
Очистите путь для Мардохея и держитесь подальше от этих временных рамок.
Расчистить путь для Мордекая, держитесь подальше от временных линий.
Здесь мы находим наиболее справедливый и подходящий путь для сотрудничества в развитии наших народов.
В этом мы находим наиболее подходящий и подходящий путь для сотрудничества в деле развития наших наций.
Объективно это не лучший путь для человечества .
Поистине, это не лучший путь для человечества.
Лучший путь для человечества — это полное исчезновение ядерного оружия.
Лучший путь для человечества — это полная ликвидация ядерного оружия.
Генеральный секретарь только что указал нам правильный путь к миру, безопасности и разоружению.
Генеральный секретарь только что путь нам надлежащий к миру, безопасности и разоружению.
Кроме того, есть три стратегических направления, которые определяют путь для МПС на следующие пять лет к реализации своего видения.
Затем указываются три стратегических направления, намечающие курс МПС к претворению в жизнь его перспективного видения на следующие пять лет.
Африка поддерживает «зеленую» экономику как путь к развитию , открывающий возможности для экономической диверсификации, создания достойных рабочих мест и борьбы с бедностью.
Африка поддерживает «зеленую» экономику в качестве пути развития, который предоставляет возможности для диверсификации экономики, услуг достойных мест и борьбы с нищетой.
Она считает раунд в Дохе лучшим путем для решения таких проблем.
Делегация считает Дохинский раунд лучшим способом разрешения этих проблем.
Энергетическая инициатива может стать стратегическим направлением для будущей программной ориентации Организации.
Инициатива в области энергетики, возможно, является одним из стратегических ориентиров для будущих программ Организации.
В этой связи Эквадор проложил путь к , сокращая «цифровой разрыв» в обществе.
В этой связи Эквадор наметил для себя курс сокращения цифрового разрыва внутри общества.
И кольцо … другое открывает путь для вас.
И позвоню… на другие станции … чтобы открыть для вас путь .
.
Почему вам следует использовать pathlib / Хабр
От переводчика: Привет, хабр! Представляю вашему вниманию перевод статьи Почему вы должны использовать pathlib и её продолжения? Нет, правда, pathlib великолепен. Много внимания нынче уделяется таким новым возможностям Python, как asyncio, оператору: =, и опциональной типизации. При этом за радаром рискуют пройти не столь значительно (хотя,: = назвать серьёзным нововведением язык не поворачивается), но весьма полезные нововведения в язык.В частности, на хабре статей, посвященных сабжу, я не нашел (кроме одного абзаца тут), поэтому решил исправить ситуацию.
Когда я открыл для себя тогда еще новый модуль pathlib несколько лет назад, это лишь слегка неуклюжая объектно-ориентированная версия модуля os.path
. Я ошибался. pathlib
на самом деле чудесен!
В этой статье я попытаюсь вас влюбить в pathlib
. Я надеюсь, что статья вдохновит вас использовать pathlib
в любой ситуации, касающейся работы с файлами в Python .
Часть 1.
os.path
неуклюж
Модуль os.path
всегда был тем, что мы использовали когда речь заходила про пути в Python. В принципе, там есть всё, что вам нужно, но выглядит это не слишком изящно.
Стоит ли импортировать его так?
импорт os.path
BASE_DIR = os.path.dirname (os.path.dirname (os.path.abspath (__ file__)))
TEMPLATES_DIR = os.path.join (BASE_DIR, 'templates')
Или так?
из ос.путь import abspath, dirname, join
BASE_DIR = имя каталога (имя каталога (abspath (__ file__)))
TEMPLATES_DIR = join (BASE_DIR, 'templates')
Может быть функция join
имеет слишком общее название, и нам стоит сделать что-то такое:
из os.path import abspath, dirname, join as join as
BASE_DIR = имя каталога (имя каталога (abspath (__ file__)))
TEMPLATES_DIR = joinpath (BASE_DIR, 'templates')
Мне все варианты выше кажутся не слишком удобными. Мы передаём строки в функциях, которые возвращают строки, которые мы передаём следующей функцией, работающим со строками.Так уж случилось, что они все содержат пути, но они всё еще всего строки.
Использование строк для ввода и вывода в функциях os.path
весьма неудобное, потому что код приходится читать изнутри наружу. Хотелось бы преобразовать эти вызовы из вложенных в последовательные. Именно это и позволяет сделать pathlib
!
из пути импорта pathlib
BASE_DIR = Путь (__ файл __). Resolve (). Parent.parent
TEMPLATES_DIR = BASE_DIR.joinpath ('шаблоны')
Модуль os.path
требует вложенных функций, но pathlib
позволяет нам создать цепочки последовательных методов и атрибутов класса Path
с эквивалентным результатом.
Я знаю что вы думаете: стоп, эти объекты Путь
— не то же самое, что было раньше, мы больше не оперируем строками путей! К этому вопросу вернёмся позже (подсказка: почти в любой ситуации эти два подхода взаимозаменяемы).
os
перегружен
Классический модуль os.путь
предназначенный для работы с путями. сделать путём (например, создать директорию), вам нужно обращаться к другому модулю, часто, os
.
os
содержит кучу утилит для работы с файлами и директориями: mkdir
, getcwd
, chmod
, stat
, remove
, rename
, rmdir
. Также chdir
, link
, walk
, listdir
, makedirs
, переименовывает
, removeirs
, unlink
, symlink
.И еще кучу всякой всячины, не с файловыми системами совершенно: вилка
, getenv
, putenv
, environment
, getlogin
, system
,… Еще несколько дюжин вещей, о которых я буду упоминать здесь не буду .
Модуль os
предназначен для широкого круга; задач это такой ящик со всем, система с операционной системой. Есть много полезностей в OS
, но в нём не всегда легко ориентироваться: необходимо слегка покопаться в модуле, прежде чем вы найдёте то, что нужно.
pathlib
переносит большинство функций по работе с файловой системой в объектах Path
.
Вот код, который создаёт директорию src / __ pypackages__
и переименовывает наш файл .editorconfig
в src / .editorconfig
:
import os
импорт os.path
os.makedirs (os.path.join ('src', '__pypackages__'), exist_ok = True)
os.rename ('. editorconfig', os.path.join ('src', '.editorconfig'))
Вот аналогичный код, использующий Path
from pathlib import Path
Путь ('src / __ pypackages__').mkdir (родители = True, exist_ok = True)
Путь ('. Editorconfig'). Rename ('src / .editorconfig')
Заметьте, что второй пример гораздо проще читать, потому что он организован слева направо — это всё благодаря цепочкам методами.
Не забывайте про glob
Не только os
и os.path
содержат методы, связанные с файловой системой. Также стоит упомянуть про glob
, нельзя назвать бесполезным.
Мы можем использовать функцию glob.glob
для поиска файлов по определенному шаблону:
от glob import glob
top_level_csv_files = glob ('*. csv')
all_csv_files = glob ('** / *. csv', recursive = True)
Модуль pathlib
также предоставляет аналогичные методы:
from pathlib import Path
top_level_csv_files = путь.cwd (). glob ('*. csv')
all_csv_files = Path.cwd (). rglob ('*. csv')
После перехода на модуль pathlib
, необходимость в модуле glob
пропадает полностью : всё необходимое уже является составной частью объектов Path
pathlib
делает вещи еще
pathlib
упрощает сложные сложные ситуации, но помимо этого делает некоторые простые фрагменты кода еще проще .
Хотите прочитать весь текст в одном или нескольких файловх?
Можете открыть файл, прочитать содержимое и закрыть файл, используя блок с помощью
:
от glob import glob
file_contents = []
для имени файла в glob ('** / *. py', recursive = True):
с open (имя файла) как python_file:
file_contents.append (python_file.read ()
Или можно использовать метод read_text
на объекте Path
и генерацию списков, что бы получить аналогичный результат за одно выражение:
from pathlib import Path
file_contents = [
дорожка.read_text ()
для пути в Path.cwd (). rglob ('*. py')
]
А что, если нужно записать в файл?
Вот как это выглядит, используя open
:
с open ('. Editorconfig') в качестве конфигурации:
config.write ('# config идет здесь')
Или же вы можете использовать метод write_text
:
Path ('. editorconfig'). write_text ('# config go here')
-либо причины вам необходимо использовать open
, либо в качестве контекстного менеджера, либо по другим предпочтениям, Path
использует метод open
, в качестве альтернативы:
from pathlib import Path
path = Путь ('.editorconfig ')
с path.open (mode = 'wt') как config:
config.write ('# config go here')
Или же, начиная с Python 3.6, можно передать ваш Путь
напрямую в открыть
:
из пути импорта pathlib
путь = Путь ('. editorconfig')
с open (path, mode = 'wt') как config:
config.write ('# здесь идет config')
Объекты Path делают ваш код очевиднее
На что указывают следующие переменные? Какой смысл у их значений?
person = '{"name": "Trey Hunner", "location": "San Diego"}'
pycon_2019 = "2019-05-01"
home_directory = '/ home / trey'
Каждую переменную введенную строку.Но каждая из них имеет разные значения: первая — это JSON, вторая — дата, и третья — это файловый путь.
Вот такое представление объектов слегка полезнее:
from datetime import date
from pathlib import Path
person = {"name": "Трей Ханнер", "location": "Сан-Диего"}
pycon_2019 = дата (2019, 5, 1)
home_directory = Path ('/ home / trey')
Объекты JSON можно десериализовать в словарь, дату можно нативно представить, используя datetime.date
, а объектов файловых путей можно представить в виде Path
Использование объектов Путь
делает ваш код более явным.Если вы хотите работать с датами, вы используете от
. Если хотите работать с файлами путями, використовуйте Path
.
Я не особо большой сторонник ООП. Классы добавить дополнительный слой абстракции, а абстракции иногда свойственно усложнять систему, а не упрощать. При этом я считаю, что pathlib.Path
— это полезная абстракция . Довольно быстро она становится общепринятым решением.
PEP 519, Path
становятся стандартными для работы с путями.На момент Python 3.6, большинство методов os
, shutil
, os.path
корректно работают с этим объектомми. Вы можете уже сегодня перейти на использование pathlib
, прозрачно для вашей кодовой базы!
Чего не хватает в pathlib
?
Хотя pathlib
и классная, но не всеобъемлющая. Определённо есть , были включены несколько возможностей, которые были включены в модуль .
Первое, недостаток приходит на ум, этоок методов у Path
, эквивалентных shutil
. И хотя вы можете объекты Path
как параметры shutil
для копирования / удаления / перемещения файлов и директорий, вызвать их методы у Path
не получится.
Так что, для копирования файлов, необходимо сделать что-то вроде этого:
from pathlib import Path
from shutil import copyfile
source = Путь ('старый_файл.текст')
назначение = Путь ('новый_файл.txt')
copyfile (источник, назначение)
Также нет аналога метода os.chdir
. Это означает, что вам необходимо её импортировать, если возникнет необходимость сменить текущую директорию:
из pathlib import Path
из os import chdir
parent = Путь ('..')
chdir (родитель)
Также нет эквивалента функции os.walk
. Хотя вы можете написать свою функцию в духе walk
без особых сложностей.
Я надеюсь что однажды объекты pathlib.Path
будут содержать методы для некоторых из упомянутых операций. Но даже при таком раскладе я представляю более простой подход «использовать pathlib
с чем-то еще» чем «использовать os.path
и всё остальное» .
Всегда ли использовать pathlib
?
Начало с Python 3.6, Path работают практически везде, где вы используете строки . Так что я не вижу причин не использовать pathlib
, если вы используете Python 3.6 и выше.
Если же вы используете более раннюю версию Python 3, вы в любой момент можете обернуть объект Путь
в вызов str
что бы получить, если возникла необходимость вернуться в страну строчек. Это не слишком изящно, но работает:
из os import chdir
from pathlib import Path
chdir (Path ('/ home / trey')) # Работает в Python 3.6+
chdir (str (Path ('/ home / trey'))) # Работает в более старых версиях
Часть 2. Ответы на вопросы.
После публикации первой части у некоторых людей возникли некоторые вопросы. Кто-то говорил, что я сравнивал библиотеку os.path
и pathlib
нечестно. Некоторые говорили, что использование os.path
настолько укоренилось в сообществе Python, что переходит на новую библиотеку займёт очень большой промежуток времени. Еще я видел некоторые вопросы по поводу производительности.
В этой части я бы хотел прокомментировать эти вопросы. Можно считать это одновременно защитой pathlib
и чем-то вроде любовного письма к PEP 519.
Сравнение os.path
и pathlib
по-честному
В прошлой части я сравнивал следующие два фрагмента кода:
import os
импорт os.path
os.makedirs (os.path.join ('src', '__pypackages__'), exist_ok = True)
os.rename ('. editorconfig', os.path.join ('src', '.editorconfig'))
из пути импорта pathlib
Путь ('src / __ pypackages __'). Mkdir (parent = True, exist_ok = True)
Путь ('. Editorconfig'). Rename ('src / .editorconfig')
Это может показаться нечестным сравнением, потому что использование os.path.join
в первом примере использование корректных разделителей на всех платформах, чего я не делал во втором примере. На самом деле, всё в порядке, потому что Path автоматически адаптирует разделители путей
Мы можем доказать это, посмотрев на преобразование объекта Path
в строке на Windows:
>>> str (Path ('src / __pypackages__ '))
'src \\ __ pypackages__'
Без разницы — использовать ли мы метод joinpath
, '/'
в строке пути, оператор /
(еще одна приятная фишка Path
) или передаём отдельные аргументы в конструкторе Path , мы получаем одинаковый результат:
>>> Path ('src', '.editorconfig ')
WindowsPath ('src / .editorconfig')
>>> Путь ('src') / '.editorconfig'
WindowsPath ('src / .editorconfig')
>>> Путь ('src'). Joinpath ('. Editorconfig')
WindowsPath ('src / .editorconfig')
>>> Путь ('src / .editorconfig')
WindowsPath ('src / .editorconfig')
Последний пример предложения замешательства от людей, которые предполагали, что pathlib
недостаточно умён для замены /
на \
в данном пути. К счастью, всё в порядке!
С объектами Путь
, вам больше не нужно беспокоиться по направлениям слэшей: определяйте все свои пути с использованием /
, и результат будет предсказуем для любой платформы.
Вы не должны беспокоиться об нормализации путей сообщения
Если вы работаете на Linux или Mac, очень легко случайно добавить в код баги, которые включают только пользователей Windows. Если не использовать внимательно использование os.path.join
и \ или os.path.normcase
для конвертации слэшей в подходящие для текущей платформы , вы можете написать код, который не будет корректно работать в Windows .
Вот пример Windows-specific бага:
import sys
импорт ос.дорожка
каталог = '.' если не sys.argv [1:] иначе sys.argv [1]
new_file = os.path.join (каталог, 'new_package / __ init__.py')
При этом такой код будет работать корректно везде:
import sys
from pathlib import Path
каталог = '.' если не sys.argv [1:] иначе sys.argv [1]
new_file = Path (directory, 'new_package / __ init__.py')
Ранее программист был ответственен за конкатенацию и нормализацию путей, так же, как в Python 2 программист был ответственен за решение, где стоит использовать юникод вместо байтов.Больше это не ваша задача — все похожие проблемы Path
решает за вас.
Я не использую Windows, и у меня нет компьютера с Windows. Это огромное количество людей, которые будут использовать мой код, очень вероятно будут использовать Windows, и я хочу, чтобы у них всё работало корректно.
Если есть вероятность, что ваш код будет запускаться на Windows, вам стоит серьёзно задуматься над переходом на pathlib
.
Не беспокойтесь о нормализации : используйте Path
в любом случае, когда речь заходит о путях к файлам.
Звучит классно, но у меня сторонняя библиотека, которая не pathlib
!
У вас большая кодовая база, которая работает со строками в качестве путей. Зачем переходить на pathlib
, если это означает, что всё нужно переписывать?
Давайте представим, что у вас есть следующая функция:
import os
импорт os.path
def make_editorconfig (dir_path):
"" "Создать файл .editorconfig в указанном каталоге и вернуть имя файла."" "
имя_файла = os.path.join (dir_path, '.editorconfig')
если не os.path.exists (имя файла):
os.makedirs (dir_path, exist_ok = True)
open (имя файла, режим = 'вес'). запись ('')
return filename
Функция принимает директорию, и создаёт там файл .editorconfig
, примерно так:
>>> import os.path
>>> make_editorconfig (os.path.join ('src', 'my_package'))
'src / my_package / .editorconfig'
Если заменить строки на Path
, всё тоже заработает:
>>> from pathlib import Path
>>> make_editorconfig (Путь ('src / my_package'))
src / my_package /.editorconfig '
Но… как?
os.path.join
принимает объекты Path
(начиная с Python 3.6). То же самое можно сказать и про os.makedirs
.
На самом деле, встроенная функция open
принимает Path
, shutil
принимает Path
и всё, что в стандартной библиотеке раньше принимало строку, теперь должно работать как с Path
, так и со строками.
За это стоит благодарить PEP 519, который предоставил абстрактный класс os.PathLike
и объявил, что все встроенные утилиты для работы с путями к файлам теперь должны работать как со строками, так и с Path
.
Но в моей любимой библиотеке есть Path, лучше стандартного!
Возможно, вы уже используете свою стороннюю библиотеку, которая использует свою Path 9, которая отличается от стандартной. Возможно, она вам нравится больше.
Например, django-environmental, path.py, plumbum, и visidata содержат свои собственные объекты Path
.Некоторые из этих библиотек старше , pathlib
, приняли решение наследоваться от str
, что бы их можно было передать функции, ожидающие строки в качестве путей. Благодаря PEP 519, интеграция сторонних библиотек в ваш код будет проще, и без необходимости наследования от str
.
Давайте представим, что вы не хотите использовать pathlib
, потому что Path
- иммутабельные объекты, а вам ну прям очень хочется изменить их состояние.Благодаря PEP 519 вы можете создать свою самую лучшую-мутабельную версию Path
. Для этого достаточно реализовать метод __fspath__
Любая самостоятельно реализованная реализация Path
теперь может нативно работать со встроенными функциями Python, которые ожидают файловые пути. Даже если вам не нравится pathlib
, сам факт ее существования - это большой плюс для сторонних библиотек с собственными Path
Но ведь pathlib.Path
и str
не смешиваются, правда?
Вы возможно думаете: это всё, конечно, здорово, но разве этот подход с-иногда строка-а-иногда-path не добавит ли сложности в мой код?
Ответ на этот вопрос - да, в некоторой степени. Но у этой проблемы есть довольно простой обход.
PEP 519 добавил еще несколько вещей, помимо PathLike
: во-первых, это способ конвертировать PathLike
в строку, а во-втором, это способ любой PathLike
превратить в Path
.
Возьмём два объекта - строку и Путь
(или что угодно с методом fspath ):
из pathlib import Path
импорт os.path
p1 = os.path.join ('src', 'мой_пакет')
p2 = Path ('src / my_package')
Функция os.fspath
нормализирует оба объекта и превратит в строки:
>>> from os import fspath
>>> fspath (p1), fspath (p2)
('src / my_package', 'src / my_package')
При этом, Path
может принять оба этих объекта в конструктор и преобразовать их в Path
:
>>> Path (p1), Path ( p2)
(PosixPath ('src / my_package'), PosixPath ('src / my_package'))
Это означает, что вы можете преобразовать результат make_editorconfig
назад в Path
при необходимости:
>>> from pathlib import Дорожка
>>> Путь (make_editorconfig (Путь ('src / my_package')))
PosixPath ('src / my_package /.editorconfig ')
Хотя, конечно, лучшим решением было бы переписать make_editorconfig
, используя pathlib
.
pathlib
слишком медленный
Я видел несколько вопросов по производительности pathlib
. Это правда - pathlib
может быть медленным. Создание тысяч объектов Путь
может заметно сказаться на поведении программы.
Я решил замерить производительность pathlib
и os.path
на своём компьютере, используя две разные программы, которые ищут все .py
файлы в текущей директории
Вот версия os.walk
:
из os import getcwd, walk
extension = '.py'
count = 0
для корня, каталогов, имен файлов в walk (getcwd ()):
для имени файла в именах файлов:
если filename.endswith (расширение):
count + = 1
print (f "{count} Python files found")
А вот версия с Path.rglob
:
from pathlib import Path
extension = '.py '
count = 0
для имени файла в Path.cwd (). rglob (f '* {extension}'):
count + = 1
print (f "{count} найдены файлы Python")
Тестирование производительности программ, которые работают с файловой системой - задача хитрая, потому что время работы может меняться довольно сильно. Я решил запустить каждый скрипт 10 раз и сравнил лучшие результаты для каждой программы.
Обе программы нашли 97507 файла в директории, в которой я их запускал. Первый сработал за 1.914 секунды, второй закончил работу за 3.430 секунды.
Когда я установил параметр extension = ''
, эти программы находят примерно 600 000 файлов, и разница увеличивается. Первая программа сработала за 1.888 секунд, а вторая за 7.485 секунд.
Так что, pathlib
работает примерно вдвое медленнее для файлов с расширением .py
, и в четыре раза медленнее при запуске на моей домашней директории. Относительный разрыв в производительности pathlib
и os
весьма велик.
В моём случае, эта скорость мало что меняет. Я искал все файлы в своей директории и потерял 6 секунд. Если бы у меня была задача обработать 10 миллионов файлов, я бы скорее всего ее переписал. Но пока такой необходимости нет, можно и подождать.
Если у вас есть горячий фрагмент кода, и pathlib
явно негативно влияет на его работу, нет ничего плохого в том, что бы заменить его на альтернативу. Не стоит оптимизировать код, который не используется узким местом - это лишняя трата времени, которая к тому же обычно приводит к плохо читаемому коду, без особого выхлопа.
Улучшение читаемости
Я хотел бы закончить этот поток мыслей некоторыми примерами рефакторинга при помощи pathlib
. Я взял несколько примеров кода, который работает с людьми. Оставлю большую часть кода без комментариев на ваш суд - решайте, какая версия вам нравится больше.
Вот функция make_editorconfig
, которую мы видели ранее:
import os
импорт os.path
def make_editorconfig (dir_path):
"""Создайте .editorconfig в заданном каталоге и вернуть имя файла. "" "
имя_файла = os.path.join (dir_path, '.editorconfig')
если не os.path.exists (имя файла):
os.makedirs (dir_path, exist_ok = True)
open (имя файла, режим = 'вес'). запись ('')
return filename
А вот версия, переписанная на pathlib
:
from pathlib import Path
def make_editorconfig (dir_path):
"" "Создать файл .editorconfig в указанном каталоге и вернуть путь к файлу." ""
path = Путь (dir_path, '.editorconfig ')
если не path.exists ():
path.parent.mkdir (exist_ok = True, parent = True)
path.touch ()
путь возврата
Вот консольная программа которая использует с директорией и печатает содержимое файла .gitignore
, если он существует:
import os.path
import sys
directory = sys.argv [1]
ignore_filename = os.path.join (каталог, '.gitignore')
если os.path.isfile (ignore_filename):
с open (ignore_filename, mode = 'rt') как ignore_file:
печать (ignore_file.read (), end = '')
То же самое, но с pathlib
:
из pathlib import Path
import sys
каталог = Путь (sys.argv [1])
ignore_path = каталог / '.gitignore'
если ignore_path.is_file ():
print (ignore_path.read_text (), end = '')
Вот программа, которая печатает все дублирующиеся файлы в текущей папке и подпапках:
из коллекций import defaultdict
из hashlib import md5
из ОС импортировать getcwd, пройтись
импорт os.path
def find_files (путь к файлу):
для корня, каталогов, имен файлов в обходе (путь к файлу):
для имени файла в именах файлов:
урожай ос.path.join (корень, имя файла)
file_hashes = defaultdict (список)
для пути в find_files (getcwd ()):
с open (path, mode = 'rb') как my_file:
file_hash = md5 (мой_файл.read ()). hexdigest ()
file_hashes [file_hash] .append (путь)
для путей в file_hashes.values ():
если len (пути)> 1:
print ("Обнаружены повторяющиеся файлы:")
print (* paths, sep = '\ n')
То же самое, но c pathlib
:
из коллекций import defaultdict
из hashlib import md5
from pathlib import Path
def find_files (путь к файлу):
для пути в Path (путь к файлу).rglob ('*'):
если path.is_file ():
путь уступки
file_hashes = defaultdict (список)
для пути в find_files (Path.cwd ()):
file_hash = md5 (путь.read_bytes ()). hexdigest ()
file_hashes [file_hash] .append (путь)
для путей в file_hashes.values ():
если len (пути)> 1:
print ("Обнаружены повторяющиеся файлы:")
print (* пути, sep = '\ n')
Изменения незначительных, но, по-моему, в сумме дают положительный результат. Я лично предпочитаю варианты с использованием pathlib
.
Начните использовать объекты pathlib.Path
Давайте повторим.
Раздел /
в строках pathlib.Path
автоматически конвертируется в правильный разделитель для текущей операционной системы. Это важная особенность, которая делает код более читаемым и избавляет от особенных багов .
>>> путь2 = Путь ('каталог', 'файл')
>>> путь3 = Путь ('каталог') / 'файл'
>>> path4 = Путь ('каталог / файл')
>>> путь4
WindowsPath ('каталог / файл')
>>> путь2 == путь3 == путь4
True
Встроенные функции Python (напр. открыто
) также принимают Path
, то есть вы можете использовать pathlib
, если даже ваши сторонние библиотеки этого не делают!
из shutil import move
def rename_and_redirect (old_filename, new_filename):
переместить (старый, новый)
с open (old, mode = 'wt') как f:
f.write (f'Этот файл перемещен в {новый} ')
>>> from pathlib import Path
>>> old, new = Путь ('old.txt'), Путь ('new.текст')
>>> rename_and_redirect (старый, новый)
>>> old.read_text ()
«Этот файл перемещен в new.txt»
И если вам не нравится pathlib
, вы можете использовать стороннюю библиотеку, которая реализует интерфейс PathLike
. Это отлично, потому что даже если вам не нравится стандартная реализация, вы все равно получите выгоду от изменений в PEP 519 .
>>> from plumbum import Path
>>> my_path = Путь ('старый.текст')
>>> с open (my_path) как f:
... печать (f.read ())
...
Этот файл перемещен в new.txt
И хотя pathlib
может быть медленнее альтернативой, обычно это не так важно (по крайней мере, мой опыт показывает так), к тому же вы всегда можете вернуться к использованию строк для фрагментов кода, чувствительных к производительности .
В целом, pathlib
позволяет писать более читаемый код. Вот короткий ёмкий скрипт на Python для иллюстрации моей точки зрения:
из pathlib import Path
gitignore = Путь ('.gitignore ')
если gitignore.is_file ():
print (gitignore.read_text (), end = '')
Модуль pathlib
- отличный. Начните же его использовать!
.
path - Перевод на русский - примеры английский
Предложения:
карьерная лестница
путь роста
На основании вашего запроса эти примеры могут содержать грубую лексику.
На основании вашего запроса эти примеры могут содержать разговорную лексику.
Эта Глобальная программа действий намечает путь и вперед для инициативы и ее заинтересованных сторон.
В этой Глобальной программе действий определен путь продвижения вперед в этой кампании, которые используют и задействованные в ней заинтересованные стороны.
И я надеюсь, что когда-нибудь этот путь заслужит мне ваше прощение.
И я надеюсь, что однажды, этот путь заслужит твоё прощение.
Эти примеры показывают путь , которому следует следовать .
Эти примеры указывают на направление , в котором нужно двигаться.
Поэтому он призвал Словакию продолжить путь .
В этой связи привидение новой роли в этом направлении .
Ян-ру в конце концов перенес операцию и сейчас находится на пути к выздоровлению .
В итоге Яньжу была сделана операция, и сейчас она находится на пути к выздоровлению.
Мы продвигались, убивая всех повстанцев, которые пересекали наш путь .
Мы продвигались, убивая каждого мятежника, который вставал на нашем пути .
Трав выбрал этот путь , потому что ему это нравится.
Тревис выбрал этот путь потому, что он любит это.
Этот путь в гору ветер летит ...
Тот путь вверх по склону, которому путешествует ветер.
Большая поддержка - это самый короткий путь к независимости.
Предоставление более существенной поддержки - это кратчайший путь к обретению независимости.
Следовательно, проблема самого длинного пути является NP-сложной.
Таким образом, задача поиска самого длинного пути является NP-трудной.
Каждый путь развития содержит уникальные юниты и возможности.
Какой бы путь развития ни был выбран, на нём доступны уникальные юниты и возможности.
К сожалению, Джуди выбрала путь .
К сожалению, Джуди сама выбрала этот путь ».
Это открыло бы путь к полной самореализации.
Это будет означать, что открывается путь к полной самореализации.
Добавлен путь для хранения ранее открытого файла резервной копии.
Добавлено запоминание и отображение пути к папке файлов архивных копий.
Его сигнал повреждает все на своем пути .
Зонд движется к нам, повреждая все на своем пути .
Вы выбрали этот путь : следуйте по нему.
Вы избрали свой путь , следуйте же по нему.
Ты знаешь свой путь , дитя.
Ты знаешь, где твой путь , дитя.
Однако на его пути есть множество препятствий.
Но, как оказывается, на его пути начинают возникать препятствия.
Десять лет спустя Лафортюн предложил множество усовершенствований, в том числе двунаправленную трассировку пути и .
Позже в этом году Лафортюн (англ. Lafortune) использует много усовершенствований алгоритма, в том числе путём двунаправленной трассировки пути .
Объект с пакетом путь не предоставляет настраиваемые свойства.
Объект, расположенный по следующему пути к пакету, не имеет настраиваемых свойств..
работа с файловой системой / Корпоративный блог RUVDS.com / Хабр
Сегодня, в девятой части перевода руководства по Node.js, мы поговорим о работе с файлами. В частности, речь пойдёт о модулях fs и path - о файловых дескрипторах, о путях к файлам, о получении информации о файлах, об их чтении и записи, о работе с директориями.
[Советуем почитать] Другие части цикла Часть 1: Общие сведения и начало работы
Часть 2: JavaScript, V8, некоторые приёмы разработки
Часть 3: Хостинг, REPL, работа с консолью, модули
Часть 4: npm, файлы package.json и package-lock.json
Часть 5: npm и npx
Часть 6: цикл событий, стек расписания, таймеры
Часть 7: асинхронное программирование
Часть 8: Руководство по Node.js, часть 8: протоколы HTTP и WebSocket
Часть 9: Руководство по Node.js, часть 9: работа с файловой системой
Часть 10: Руководство по Node.js, часть 10: стандартные модули, потоки, базы данных, NODE_ENV
Полная PDF-версия руководства по Node.js
Работа с файловыми дескрипторами в Node.js
Вам необходимо получить дескриптор файла.
Дескриптор можно получить, воспользовавшись для открытия файла асинхронным методом open ()
из модуля fs
:
const fs = require ('fs')
fs.open ('/ Users / flavio / test.txt', 'r', (err, fd) => {
// fd - это дескриптор файла
})
Обратите внимание на второй параметр, r
, используемый при вызове метода fs.открыть ()
. Это - флаг, который сообщает системе о том, что файл открывают для чтения. Вот ещё некоторые флаги, которые используются при работе с этим и другими методами:
-
r +
- открыть файл для чтения и для записи. -
w +
- открыть файл для чтения и для записи, установив указатель потока в начало файла. Если файл не существует - он создаётся. -
a
- открыть файл для записи, установив указатель потока в конец файла.Если файл не существует - он создаётся. -
a +
- открыть файл для чтения и записи, установив указатель потока в конец файла. Если файл не существует - он создаётся.
Файлы можно открывать и использовать синхронным методом fs.openSync ()
, который вместо того, чтобы предоставить дескриптор файла в коллбэке, возвращает его:
const fs = require ('fs')
пытаться {
const fd = fs.openSync ('/ Пользователи / flavio / test.txt', 'r')
} catch (err) {
консоль.ошибка (ошибка)
}
После получения дескриптора любым из вышеописанных способов вы можете с ним обязательные операции.
Данные о файлах
С помощью каждого случая связан набор данных о нём, исследовать эти данные можно средствами Node.js. В частности, сделать это можно, используя метод stat ()
из модуля fs
.
Вызывают этот метод, передавая ему путь к файлу, и, после того, как Node.js получает необходимые сведения о файле, он вызывает коллбэк, переданный методу stat ()
.Вот как это выглядит:
const fs = require ('fs')
fs.stat ('/ Users / flavio / test.txt', (err, stats) => {
if (err) {
console.error (ошибка)
возвращение
}
// сведения о существующем в аргументе `stats`
})
В Node.js имеется возможность синхронного получения сведений о файлах. При таком подходе главный поток блокируется до получения свойств файла:
const fs = require ('fs')
пытаться {
const stats = fs.statSync ('/Users/flavio/test.txt')
} catch (err) {
консоль.ошибка (ошибка)
}
Информация о файле попадёт в константу , статистика
. Что это за информация? На самом деле, соответствующий объект нам использует большое количество полезных свойств и методов:
- Методы
.isFile ()
и.isDirectory ()
позволяют, соответственно, узнать, исследуемый файл обычным файлом или директорией. - Метод
.isSymbolicLink ()
позволяет узнать, является ли файл символической ссылки. - Размер файла можно узнать, воспользовавшись своимством
.size
.
Тут имеются и другие методы, но эти - самые употребимые. Вот как ими пользоваться:
const fs = require ('fs')
fs.stat ('/ Users / flavio / test.txt', (err, stats) => {
if (err) {
console.error (ошибка)
возвращение
}
stats.isFile () // истина
stats.isDirectory () // ложь
stats.isSymbolicLink () // ложь
stats.size // 1024000 // = 1 МБ
})
Пути к файлам в Node.js и путь модуля
Путь к файлу - это адрес того места в файловой системе, где он расположен.
В Linux и macOS путь может выглядеть так:
/users/flavio/file.txt
В Windows пути выглядят немного иначе:
C: \ users \ flavio \ file.txt
На различных форматах записи путей при разных операционных системах следует обращать внимание, используемую для развёртывания Node.js-сервера.
В Node.js есть стандартный модуль path
, предназначенный для работы с путями к файлам. Перед использованием этого модуля в программе его надо подключить:
const path = require ('path')
▍Получение информации о пути к файлу
Если у вас есть путь к файлу, используя возможности модуля path
, вы можете, в удобном для восприятия и дальнейшей обработки виде узнать подробности об этом пути. Выглядит это так:
const notes = '/ users / flavio / notes.текст'
path.dirname (заметки) // / пользователи / flavio
path.basename (заметки) // notes.txt
path.extname (заметки) // .txt
Здесь, в строке заметки
, хранится путь к файлу. Для разбора пути используемые следующие методы модуля path
:
-
dirname ()
- возвращает родительскую директорию файла. -
basename ()
- возвращает имя файла. -
extname ()
- возвращает расширение файла.
Узнать имя файла без расширения можно, вызвав метод .basename ()
и ему передается второй аргумент, представляющий расширение:
path.basename (notes, path.extname (notes)) // notes
▍Работа с путями к файлам
Несколько частей пути можно объединить, используя метод path.join ()
:
const name = 'flavio'
path.join ('/', 'пользователи', имя, 'notes.txt') //'/users/flavio/notes.txt '
Абсолютный путь к файлу на основе относительного пути к нему можно использовать путь метода .resolve ()
:
путь.resolve ('flavio.txt')
//'/Users/flavio/flavio.txt 'при запуске из моей домашней папки
В данном случае Node.js просто /flavio.txt
к пути, ведущий к текущей директории. Если при вызове этого метода передать ещё один параметр, представляющий путь к файлу, метод использует его в качестве базы данных для определяющего пути:
path.resolve ('tmp', 'flavio.txt')
// '/Users/flavio/tmp/flavio.txt' при запуске из моей домашней папки
Если путь, переданный в первом руководстве, начинается с косой черты - это означает, что он представляет собой абсолютный путь.
path.resolve ('/ etc', 'flavio.txt')
// '/etc/flavio.txt'
Вот ещё один полезный метод - path.normalize ()
. Он позволяет найти реальный путь к файлу, используя путь, в котором используются спецификации относительного пути точки (.
), двух точек ( ..
), или двух косых черт:
path.normalize ('/ users / flavio /..//test.txt ')
// /users/test.txt
Методы resolve ()
и normalize ()
не проверяют существование директории.Они просто находят путь, алгоритм на переданным им данным.
Чтение файлов в Node.js
Самый простой способ чтения файлов в Node.js заключается в использовании метода fs.readFile ()
с передачей ему пути к файлу и коллбэка, который вызван передачей ему данных файла (или объекта ошибки):
fs.readFile (' /Users/flavio/test.txt ', (ошибка, данные) => {
if (err) {
console.error (ошибка)
возвращение
}
console.log (данные)
})
Если надо, можно воспользоваться синхронной версией этого метода - fs.readFileSync ()
:
const fs = require ('fs')
пытаться {
const data = fs.readFileSync ('/ Пользователи / flavio / test.txt')
console.log (данные)
} catch (err) {
console.error (ошибка)
}
По умолчанию при чтении файлов используется кодировка utf8
, но кодировку можно задать и самостоятельно.
Методы fs.readFile ()
и fs.readFileSync ()
считывают в память всё содержимое файла. Это означает, что работа с большими объемами использования этих методов серьёзно отразится на потреблении вашей памяти и окажет влияние на его производительность.Лучше всего запустить потоками.
Запись файлов в Node.js
В Node.js легче всего записывать файлы с использованием метода fs.writeFile ()
:
const fs = require ('fs')
const content = 'Немного содержимого!'
fs.writeFile ('/ Users / flavio / test.txt', content, (err) => {
if (err) {
console.error (ошибка)
возвращение
}
// файл записан успешно
})
Есть и синхронная версия того же метода - fs.writeFileSync ()
:
const fs = require ('fs')
const content = 'Немного содержимого!'
пытаться {
const data = fs.writeFileSync ('/ Users / flavio / test.txt', контент)
// файл записан успешно
} catch (err) {
console.error (ошибка)
}
Эти методы, по умолчанию, заменяют используемые файлы. Изменить стандартное поведение можно, воспользовавшись их флагом:
fs.writeFile ('/ Users / flavio / test.txt', content, {flag: 'a +'}, (err) => {})
Тут могут сообщить флаги, которые мы уже перечисляли в разделе, посвящённом дескрипторам.Подробности о флагах можно узнать здесь.
Присоединение данных к файлу
Метод fs.appendFile ()
(и его синхронную версию - fs.appendFileSync ()
) удобно использовать для присоединения данных к концу файла:
const content = 'Some content!'
fs.appendFile ('file.log', content, (err) => {
if (err) {
console.error (ошибка)
возвращение
}
// готово!
})
Об использовании потоков
Выше мы описывали методы, которые выполняли запись в файл, пишут в нем, если используются их синхронные версии, возвращают управление программой, а если применяются асинхронные версии - вызывают коллбэки.Если вас такое состояние не устраивает - лучше использовать потоками.
Работа с директориями в Node.js
Модуль fs
предоставляет в распоряжение инструмента много удобных методов, которые можно использовать для работы с директориями.
▍Проверка существования папки
Для того, чтобы проверить, существует ли директория и может ли Node.js получить к ней доступ, заданное разрешение, можно использовать метод fs.access ()
.
▍Создание новой папки
Для того, чтобы создать новые папки, можно использовать fs.mkdir ()
и fs.mkdirSync ()
:
const fs = require ('fs')
const folderName = '/ Пользователи / flavio / test'
пытаться {
if (! fs.existsSync (dir)) {
fs.mkdirSync (каталог)
}
} catch (err) {
console.error (ошибка)
}
▍Чтение содержимого папок
Для того, чтобы прочесть содержимое папок, можно использовать методы fs.readdir ()
и fs.readdirSync ()
. В этом примере выполняется чтение содержимого папок - то есть сведения о том, какие файлы и поддиректории в ней имеются, и возврат их относительных путей:
const fs = require ('fs')
const path = require ('путь')
const folderPath = '/ Пользователи / flavio'
фс.readdirSync (путь к папке)
Вот так можно получить полный путь к файлу:
fs.readdirSync (folderPath) .map (fileName => {
return path.join (folderPath, имя_файла)
}
Результаты можно отфильтровать для того, чтобы получить только файлы и исключить из вывода директории:
const isFile = fileName => {
вернуть fs.lstatSync (имя_файла) .isFile ()
}
fs.readdirSync (folderPath) .map (fileName => {
путь возврата. join (folderPath, fileName)). filter (isFile)
}
▍Переименование папки
Для переименования папки используйте можно методы fs.rename ()
и fs.renameSync ()
. Первый параметр - это текущий путь к папке, второй - новый:
const fs = require ('fs')
fs.rename ('/ Users / flavio', '/ Users / roger', (err) => {
if (err) {
console.error (ошибка)
возвращение
}
// готово
})
Переименовать папку можно и с помощью синхронного метода fs.renameSync ()
:
const fs = require ('fs')
пытаться {
fs.renameSync ('/ Пользователи / flavio', '/ Пользователи / Роджер')
} catch (err) {
console.error (ошибка)
}
▍Удаление папки
Для того чтобы удалить папку, можно использовать методы fs.rmdir ()
или fs.rmdirSync ()
. Надо отметить, что удаление папок, в которой что-то есть, задача несколько более сложная, чем удаление пустых папок. Если вам нужно удалить такие папки, воспользуйтесь пакетом fs-extra, который весьма популярен и хорошо поддерживается. Он представляет собой замену модуля fs
, расширяющую его возможности.
Метод remove ()
из пакета fs-extra
умеет удалять папки, в которых уже что-то есть.
Установить этот модуль можно так:
npm install fs-extra
Вот пример его использования:
const fs = require ('fs-extra')
const folder = '/ Пользователи / flavio'
фс.remove (папка, err => {
console.error (ошибка)
})
Его методами можно пользоваться в виде промисов:
fs.remove (папка) .then (() => {
// готово
}). catch (err => {
console.error (ошибка)
})
Допустимо и применение конструкции async / await:
async function removeFolder (folder) {
пытаться {
await fs.remove (папка)
// готово
} catch (err) {
console.error (ошибка)
}
}
const folder = '/ Пользователи / flavio'
removeFolder (папка)
Модуль fs
Выше мы уже сталкивались с некоторыми методами модуля fs
, применяемыми при работе с файловой системой.На самом деле, он содержит ещё много полезного. Напомним, что он не нуждается в установке, для того, чтобы запустить им в программе, его достаточно подключить:
const fs = require ('fs')
После этого у вас будет доступ к его методам, среди которых отмечены следующие, следующие из которых вам уже знакомы:
-
fs.access ()
: проверяет наличие файла и возможность доступа к нему с учётом разрешений. -
fs.appendFile ()
: присоединяет данные к файлу.Если файл не существует - он будет создан. -
fs.chmod ()
: изменяет разрешение для заданного файла. Похожие методы:fs.lchmod ()
,fs.fchmod ()
. -
fs.chown ()
: изменяет владельца и группу для заданного файла. Похожие методы:fs.fchown ()
,fs.lchown ()
. -
fs.close ()
: закрывает дескриптор файла. -
fs.copyFile ()
: копирует файл. -
фс.createReadStream ()
: создаёт поток чтения файла. -
fs.createWriteStream ()
: создаёт поток записи. -
fs.link ()
: создаёт новую жёсткую ссылку на файл. -
fs.mkdir ()
: создаёт новую директорию. -
fs.mkdtemp ()
: создаёт временную директорию. -
fs.open ()
: открывает файл. -
fs.readdir ()
: содержимое директории. -
fs.readFile ()
: считывает содержимое файла. Похожий метод:fs.read ()
. -
fs.readlink ()
: считывает значение символической ссылки. -
fs.realpath ()
: разрешает относительный путь к файлу, построенный с использованием символов.
и..
, в полный путь. -
fs.rename ()
: переименовывает файл или папку. -
fs.rmdir ()
: удаляет папку. -
fs.stat ()
: возвращает сведения о файле. Похожие методы:fs.fstat ()
,fs.lstat ()
. -
fs.symlink ()
: создаёт новую символическую ссылку на файл. -
fs.truncate ()
: обрезает файл до заданной длины. Похожий метод:fs.ftruncate ()
. -
fs.unlink ()
: удаляет файл или символическую ссылку. -
fs.unwatchFile ()
: отключает наблюдение за изменениями файлов. -
fs.utimes ()
: изменяет временную отметку файла. Похожий метод:fs.futimes ()
. -
fs.watchFile ()
: включает наблюдение за изменениями файла. Похожий метод:fs.watch ()
. -
fs.writeFile ()
: записывает данные в файл. Похожий метод:fs.write ()
.
Интересной особенностью модуля fs
является тот факт, что все его методы, по умолчанию, используются асинхронные, но существуют и их синхронные версии, которые получают путём добавления слова Sync
к именам асинхронных методов.
Например:
-
fs.rename ()
-
fs.renameSync ()
-
фс. Запись ()
-
fs.writeSync ()
Использование синхронных методов серьёзно влияет на то, как работает программа.
В Node.js 10 имеется экспериментальная поддержка этих API, основанных на промисах.
Исследуем метод fs.rename ()
. Вот асинхронная версия этого метода, использующая коллбэки:
const fs = require ('fs')
фс.rename ('before.json', 'after.json', (err) => {
if (err) {
вернуть console.error (ошибка)
}
// готово
})
При использовании его синхронной конструкции для обработки ошибок используется try / catch
:
const fs = require ('fs')
пытаться {
fs.renameSync ('до.json', 'после.json')
// готово
} catch (err) {
console.error (ошибка)
}
Используемое между вариантами использования данного метода использование метода используется в том, что во втором случае выполнения скрипта заблокировано до завершения файловой операции.
Модуль path
Модуль path, позволяющий использовать различные возможности файловой системы. Как уже было сказано, устанавливать его не нужно, так как он является частью Node.js. Для того чтобы пользоваться им, достаточно подключить:
const path = require ('path')
Свойство path.sep
этого модуля символ, использующийся для разделения сегментов пути ( \
в Windows и /
в Linux и macOS), свойство path.delimiter
даёт символ, используемый для отделения друг от друга нескольких путей (;
в Windows и :
в Linux и macOS).
Рассмотрим и проиллюстрируем примерами некоторые методы path
.
▍path.basename ()
Возвращает последний фрагмент пути. Передав второй параметр этому методу можно убрать расширение файла.
require ('path'). Basename ('/ test / something') // что-то
require ('path'). basename ('/ test / something.txt') // что-то.текст
require ('path'). basename ('/ test / something.txt', '.txt') // что-то
▍path.dirname ()
Возвращает ту часть пути, которая представляет имя директории:
require ('path'). Dirname ('/ test / something') // / test
require ('path'). dirname ('/ test / something / file.txt') // / test / something
▍path.extname ()
Возвращает ту часть пути, которая представляет расширение файла:
require ('path'). Extname ('/ test / something') // ''
require ('путь').extname ('/ test / something / file.txt') // '.txt'
▍path.isAbsolute ()
Возвращает истинное значение если путь является абсолютным:
require ('path'). IsAbsolute ('/ test / something') // true
require ('path'). isAbsolute ('./ test / something') // ложь
▍path.join ()
Соединяет несколько частей пути:
const name = 'flavio'
require ('path'). join ('/', 'users', name, 'notes.txt') //'/users/flavio/notes.txt '
▍path.нормализовать ()
Пытается выяснить реальный путь на основе пути, который содержит символы, использующиеся при построении относительных путей вроде .
, ..
и //
:
require ('path'). Normalize ('/ users / flavio /..// test.txt') ///users/test.txt
▍path.parse ()
Преобразует путь в объект, свойства которого отдельные части пути:
-
root
: корневая директория. -
dir
: путь к файлу, начиная от основной директории -
base
: имя файла и расширение. -
имя
: имя файла. -
ext
: расширение файла.
Вот пример использования этого метода:
require ('path'). Parse ('/ users / test.txt')
В результате его работы получается такой объект:
{
корень: '/',
каталог: '/ пользователи',
база: 'test.txt',
ext: '.txt',
имя: 'тест'
}
▍path.relative ()
Принимает, в качестве аргументов, 2 пути. Возвращает относительный путь из первого пути ко второму, используется на текущей рабочей директории:
require ('path').относительный ('/ Пользователи / flavio', '/Users/flavio/test.txt') //'test.txt '
require ('path'). relative ('/ Users / flavio', '/Users/flavio/something/test.txt') //'something/test.txt '
▍path.resolve ()
Находит абсолютный путь на основе переданного относительного пути:
path.resolve ('flavio.txt')
//'/Users/flavio/flavio.txt 'при запуске из моей домашней папки.
Итоги
Сегодня мы рассмотрели модули Node.js fs
и path
, которые используются для работы с файловой системой.В следующей части этой серии она завершится, мы обсудим модули OS
, событий
, http
, поговорим о работе с потоками и системами управления базами данных в Node.js.
Уважаемые читатели! Какими npm-пакетами вы пользуетесь при работе с файловой системой в Node.js?
.