Побудуйте повне ім'я файлу шляху в 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

Відповіді:


290

Це добре працює:

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, яка вже десятиліттями мертва. Та точка-плюс-три букви, яку багато хто з нас звикли бачити, є лише частиною назви файлу на всіх інших сучасних ОС, де він не має вбудованого значення.


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, розширення])) повинен це зробити. Знову ж таки, це не підриває правильності вашої відповіді.
sjbx

1
@sjbx слід розміщувати +між частинами імен файлів. os.path.join()додає /між аргументами спеціальні роздільники шляху ( наприклад) (як @ sәɹoɈ правильно вказати їх у своїй / її відповіді. Таким чином, правильна форма фрагмента вашого коду:os.path.join(dir_name, base_filename + os.extsep + extension)
Shayan Amani

40

Якщо вам пощастило запустити 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')

1
Я вважаю, що pathlib є набагато елегантнішим, ніж os.path.join, який у порівнянні здається досить незграбним.
pioniere

Не працює, якщо ім'я файлу має "." >>> filename2 = 'daily.hourly' >>> Шлях (dirname, filename2) .with_suffix (суфікс) Вихід: WindowsPath ('/ home / report / 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 навіть є функція splitext, щоб відрізати розширення. тому треба щось робити зворотним
Деймон Джуліан

2
Функція splitext зберігає значення '.' в передній частині розширення. Це, мабуть, найчистіший спосіб зробити це. Якщо ви хочете, щоб він "виглядав" чистішим у вашому коді, я б запропонував використовувати функцію або лямбда-функцію.
Vorticity

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.