Создайте полный путь к файлу в Python

181

Мне нужно передать путь к файлу в модуль. Как построить путь к файлу из имени каталога, базового имени файла и строки формата файла?

Каталог может существовать или не существовать на момент звонка.

Например:

dir_name='/home/me/dev/my_reports'
base_filename='daily_report'
format = 'pdf'

Мне нужно создать строку '/home/me/dev/my_reports/daily_report.pdf'

Конкатенация частей вручную не кажется хорошим способом. Я пробовал os.path.join:

join(dir_name,base_filename,format)

но это дает

/home/me/dev/my_reports/daily_report/pdf
Дэймон Джулиан
источник

Ответы:

291

Это прекрасно работает:

os.path.join(dir_name, base_filename + "." + filename_suffix)

Имейте в виду, что os.path.join()существует только потому, что разные операционные системы используют разные символы разделителя пути. Это сглаживает эту разницу, поэтому кросс-платформенный код не нужно загромождать особыми случаями для каждой ОС. Нет необходимости делать это для файловых «расширений» (см. Сноску), потому что они всегда связаны с остальной частью имени точкой в ​​каждой ОС.

Если использование функции в любом случае заставляет вас чувствовать себя лучше (и вам нравится ненужное усложнение кода), вы можете сделать это:

os.path.join(dir_name, '.'.join((base_filename, filename_suffix)))

Если вы предпочитаете, чтобы ваш код был чистым, просто включите точку в суффикс:

suffix = '.pdf'
os.path.join(dir_name, base_filename + suffix)

(Этот подход также оказывается совместимым с суффиксными соглашениями в pathlib , который был введен в python 3.4.)


Сноска. В операционных системах, отличных от Micorsoft, не существует такого понятия, как расширение файла. Его присутствие в Windows происходит от MS-DOS и FAT, которые позаимствовали его у CP / M, который был мертв в течение десятилетий. Точка плюс три буквы, которые многие из нас привыкли видеть, является лишь частью имени файла в любой другой современной ОС, где оно не имеет встроенного значения.

ʇsәɹoɈ
источник
7
Вы упомянули, что разделитель ОС может отсутствовать .. Для этого можно использовать os.extsep.
sjbx
2
Я не упомянул такую ​​вещь.
ɈsәɹoɈ
6
Вы пошли на несколько шагов, чтобы объяснить, что «расширения имени файла» имеют существенное значение только в одной основной операционной системе (они просто являются частью имени файла в системах, отличных от Windows), и их символ-разделитель всегда является точкой ». ОП также выразил мнение, что они увидели / pdf в конце. Так что вы могли бы сделать os.path.join(dir_name, base_filename, os.extsep, extension). Ваш ответ совершенно правильный.
sjbx
3
Да, вы правы, он возвращает только строку, поэтому os.path.join (dir_name, '' .join ([base_filename, os.extsep, extension])) должен это сделать. Опять же, это не подрывает правильность вашего ответа.
sjbx
1
@sjbx вы должны поместить +между частями имени файла. os.path.join()добавляет специфичные для ОС разделители пути ( /например) между аргументами (так как @ sәɹoɈ правильно указывает их в своем ответе. Таким образом, правильная форма вашего фрагмента кода:os.path.join(dir_name, base_filename + os.extsep + extension)
Шаян Амани
41

Если вам посчастливилось запустить Python 3.4+, вы можете использовать pathlib:

>>> from pathlib import Path
>>> dirname = '/home/reports'
>>> filename = 'daily'
>>> suffix = '.pdf'
>>> Path(dirname, filename).with_suffix(suffix)
PosixPath('/home/reports/daily.pdf')
Евгений Ярмаш
источник
2
Я считаю, что pathlib намного более элегантен, чем os.path.join, что выглядит довольно неуклюже в сравнении.
Пионер
Не работает, если у вашего имени файла есть "." >>> filename2 = 'daily.hourly' >>> Путь (dirname, filename2) .with_suffix (суффикс) Вывод: WindowsPath ('/ home / reports / daily.pdf')
wontleave
2
@wontleave: если имя файла уже имеет суффикс, он with_suffix()будет заменен вместо добавления. Вы хотите что-то вродеPath(dirname, filename2 + suffix)
Евгений Ярмаш
22

Хм, почему бы не просто

>>>> import os
>>>> os.path.join(dir_name, base_filename + "." + format)
'/home/me/dev/my_reports/daily_report.pdf'
Марк Лонгэйр
источник
спасибо, но я надеялся, что есть более чистый способ добавить это расширение. Python даже имеет функцию сплайт-текста, чтобы обрезать расширение ... так что должно быть что-то, чтобы сделать обратное
Дэймон Джулиан
2
Функция splitext сохраняет символ «.» в передней части расширения. Это, вероятно, самый чистый способ сделать это. Если вы хотите, чтобы в вашем коде он выглядел чище, я бы предложил использовать функцию или лямбда-функцию.
завихрение
0

Просто используйте, os.path.joinчтобы объединить ваш путь с именем файла и расширением. Используйте sys.argvдля доступа к аргументам, переданным скрипту при его выполнении:

#!/usr/bin/env python3
# coding: utf-8

# import netCDF4 as nc
import numpy as np
import numpy.ma as ma
import csv as csv

import os.path
import sys

basedir = '/data/reu_data/soil_moisture/'
suffix = 'nc'


def read_fid(filename):
    fid = nc.MFDataset(filename,'r')
    fid.close()
    return fid

def read_var(file, varname):
    fid = nc.Dataset(file, 'r')
    out = fid.variables[varname][:]
    fid.close()
    return out


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Please specify a year')

    else:
        filename = os.path.join(basedir, '.'.join((sys.argv[1], suffix)))
        time = read_var(ncf, 'time')
        lat = read_var(ncf, 'lat')
        lon = read_var(ncf, 'lon')
        soil = read_var(ncf, 'soilw')

Просто запустите скрипт как:

   # on windows-based systems
   python script.py year

   # on unix-based systems
   ./script.py year
альберт
источник