Для начинающих изучать алготрейдинг на Python с нуля при изучении самых простых программных кодов зачастую непонятна система формирования путей. Понятный вариант, как например “C:\My_prog\Data\fail.txt”, заменяется сложным кодом. Давайте разберемся в этом вопросе.
Имя файла
Модуль sys в Python предоставляет функционал для работы с системными параметрами и функциями интерпретатора. Нас интересует функция sys.argv — это встроенная команда, в которой перечислены все параметры командной строки, передаваемых скрипту на Python.
sys.argv – возвращает список (массив), содержащий аргументы командной строки:
- Первым элементом sys.argv[0] является имя самого запущенного скрипта
- Все последующие элементы sys.argv – это аргументы, переданные скрипту в командной строке через пробел
Создадим программу my_script.py
import sys # импортируем модуль
print(sys.argv)
print(type(sys.argv))
print(sys.argv[0])
Давайте запустим нашу программу my_script.py с помощью команды:
python my_script.py arg1 arg2 arg3 (для примера передаем некие три аргумента)
Получаем:
['my_script.py', 'arg1', 'arg2', 'arg3'] <class 'list'> my_script.py
Видно, что в первом элемента sys.argv[0] списка содержится только имя запущенного файла, без элементов списка с аргументами. И для наших целей мы будем использовать не просто sys.argv, а именно sys.argv[0].
Абсолютный путь к файлу
Модуль os.path в Python предоставляет функционал для работы с путями к файлам и каталогам. Модуль избавляет от необходимости ручного разбора строк путей и содержит кроссплатформенные реализации многих распространенных задач.
Нас интересуете функция os.path.abspath(), которая преобразует относительный путь в абсолютный.
Абсолютный путь – это путь от корневого каталога файловой системы. То есть он описывает полное расположение файла или директории.
Например:
в операционной системе Linux – /home/user/docs/my_script.py
в операционной системе Windows – C:\Users\Sergey\Documents\my_script.py
Относительные пути задают расположение относительно текущего каталога
Например: docs/files/my_script.py
Чтобы преобразовать относительный путь в абсолютный, используется функция os.path.abspath, которая дописывает относительный путь в абсолютный относительно текущей директории, в которой запущен скрипт.
Это бывает полезно для однозначного определения расположения и последующей работы с файлами по абсолютному пути.
import os.path
import sys
print(sys.argv[0])
print(os.path.abspath(sys.argv[0]))
получаем
c:/My_prog/algopack/my_script.py c:\My_prog\algopack\my_script.py
Имя директории из пути к файлу
Функция os.path.dirname() модуля os.path возвращает имя каталога в пути к директории, в которой находится текущий файл.
import os.path
import sys
print(sys.argv[0])
print(os.path.abspath(sys.argv[0]))
print(os.path.dirname(os.path.abspath(sys.argv[0])))
после запуска программы получаем
c:/_Code_home/algopack/my_script.py c:\_Code_home\algopack\my_script.py c:\_Code_home\algopack
dirname() используется для формирования путей до нужных файлов относительно расположения скрипта. Это позволяет не прописывать абсолютные пути напрямую, а собирать их динамически исходя из того, откуда запущен скрипт. Это делает программу более переносимой и независимой от конкретного места на диске.
Создаем путь до нужного нам файла или каталога
Функция os.path.join() используется для объединения одного или нескольких путей к файлам и каталогам.
Функция os.path.join обладает возможностями:
- Принимает один или более аргументов с путями
- Соединяет части пути используя разделитель в соответствии с текущей ОС (слеш или обратный слеш)
- Удаляет ненужные слеши в конце и начале путей при объединении или добавляет нужные слеши.
Функция упрощает конкатенацию (склеивание) путей и избавляет от необходимости вручную следить за разделителями и слешами.
выполнение print(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])))) выведет путь c:\My_prog\algopack
Вот и настал момент истины – теперь мы можем определить путь к любому файлу или каталогу!
Например у нас стоит задача – открыть текстовый файл “111.txt”, который лежит в одной папке с исполняемым скриптом. Код скрипта будет следующий:
import os.path
import sys
script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) # папка со скриптом
text_file = os.path.join(script_dir, '111.txt') # объединяем путь к каталогу с названием файла, собираем абсолютный путь к файлу 111.txt
with open(text_file, 'r', encoding='utf-8') as file: # Открываем файл
text = file.read() # Читаем содержимое в переменную text
print(text) # выводим содержимое файла
можно сократить код:
import os.path
import sys
with open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),'111.txt'), 'r', encoding='utf-8') as file:
text = file.read()
print(text)
Однако первый вариант все же понятен в восприятии.
А можно ли было не вникать во все вышеизложенное и открыть файл следующим образом?
with open('111.txt', 'r', encoding='utf-8') as file:
text = file.read()
print(text)
Конечно можно. Но надо учитывать, что использование модуля os.path для формирования относительных путей вместо жёстко заданных абсолютных путей имеет несколько преимуществ:
- Переносимость. Скрипт с относительными путями можно запустить из любого места файловой системы, он найдёт нужные ему файлы относительно своего расположения.
- Удобство дебага и тестирования. Не нужно менять пути при запуске скрипта на другой машине или из другой директории.
- Упрощение деплоя. При развёртывании скрипта на сервере, не нужно менять жёстко заданные пути. Достаточно скопировать файлы скрипта и ресурсов.
- Кроссплатформенность. Конструирование путей через os.path учитывает разделители в Windows и Linux.
Таким образом гибкость конструирования относительных путей в итоге экономит время и упрощает поддержку кода.
И в заключении давайте представим, что текстовый файл 111.txt, находится в папке Data рядом со скриптом. В этом случае
text_file = os.path.join(script_dir, 'Data','111.txt')
И если папка Data расположена на один уровень выше относительно скрипта, то можно еще раз скорректировать путь с помощью добавления ../
:
text_file = os.path.join(script_dir, '../Data/','111.txt')
На этом этом этапе информации по путям в программах Python для начинающего алготрейдера будет достаточно.