Cree el nombre de archivo completo de la ruta en Python

180

Necesito pasar un nombre de ruta de archivo a un módulo. ¿Cómo construyo la ruta del archivo a partir de un nombre de directorio, nombre de archivo base y una cadena de formato de archivo?

El directorio puede o no existir al momento de la llamada.

Por ejemplo:

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

Necesito crear una cadena '/home/me/dev/my_reports/daily_report.pdf'

Concatenar las piezas manualmente no parece ser una buena manera. Lo intenté os.path.join:

join(dir_name,base_filename,format)

pero da

/home/me/dev/my_reports/daily_report/pdf
Damon Julian
fuente

Respuestas:

290

Esto funciona bien:

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

Manten eso en mente os.path.join() existe solo porque diferentes sistemas operativos usan diferentes caracteres separadores de ruta. Suaviza esa diferencia para que el código multiplataforma no tenga que estar lleno de casos especiales para cada sistema operativo. No es necesario hacer esto para las "extensiones" de nombre de archivo (ver nota al pie) porque siempre están conectadas al resto del nombre con un carácter de punto, en cada sistema operativo.

Si usar una función de todos modos te hace sentir mejor (y te gusta complicar innecesariamente tu código), puedes hacer esto:

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

Si prefiere mantener limpio su código, simplemente incluya el punto en el sufijo:

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

(Este enfoque también es compatible con las convenciones de sufijos en pathlib , que se introdujo en python 3.4).


Nota al pie: No existe una "extensión" de nombre de archivo en sistemas operativos que no sean de Micorsoft. Su presencia en Windows proviene de MS-DOS y FAT, que lo tomó prestado de CP / M, que ha estado muerto durante décadas. Ese punto más tres letras que muchos de nosotros estamos acostumbrados a ver es solo parte del nombre del archivo en cualquier otro sistema operativo moderno, donde no tiene un significado incorporado.

ʇsәɹoɈ
fuente
77
Usted mencionó que el separador del sistema operativo puede no serlo .. Para esto se puede usar os.extsep.
sjbx
2
No mencioné tal cosa.
ɈsәɹoɈ
66
Hiciste todo lo posible para explicar que las "extensiones" de nombre de archivo solo tienen un significado significativo en un sistema operativo principal (simplemente son parte del nombre de archivo en sistemas que no son Windows), y su carácter separador siempre es un punto '. El OP también expresó que vieron / pdf al final. Entonces podrías haberlo hecho os.path.join(dir_name, base_filename, os.extsep, extension). Tu respuesta es perfectamente correcta.
sjbx
3
Sí, tienes razón, devuelve solo una cadena, por lo que os.path.join (dir_name, '' .join ([base_filename, os.extsep, extension])) debería hacerlo. De nuevo, no socava la exactitud de su respuesta.
sjbx
1
@sjbx debe colocar +entre partes de nombre de archivo. os.path.join()agrega separadores de ruta específicos del sistema operativo ( /por ejemplo) entre los argumentos (ya que @ sәɹoɈ los tiene correctamente en su respuesta. Por lo tanto, la forma correcta de su fragmento de código es:os.path.join(dir_name, base_filename + os.extsep + extension)
Shayan Amani
39

Si tiene la suerte de ejecutar Python 3.4+, puede usar pathlib :

>>> from pathlib import Path
>>> dirname = '/home/reports'
>>> filename = 'daily'
>>> suffix = '.pdf'
>>> Path(dirname, filename).with_suffix(suffix)
PosixPath('/home/reports/daily.pdf')
Eugene Yarmash
fuente
1
Encuentro que pathlib es mucho más elegante que os.path.join, que en comparación parece bastante torpe.
pioniere
No funciona si su nombre de archivo tiene un "." >>> filename2 = 'daily.hourly' >>> Ruta (dirname, filename2) .with_suffix (sufijo) Salida: WindowsPath ('/ home / reports / daily.pdf')
wontleave
2
@wontleave: si un nombre de archivo ya tiene un sufijo, with_suffix()lo sustituirá en lugar de agregarlo. Quieres algo comoPath(dirname, filename2 + suffix)
Eugene Yarmash
21

Um, ¿por qué no solo:

>>>> import os
>>>> os.path.join(dir_name, base_filename + "." + format)
'/home/me/dev/my_reports/daily_report.pdf'
Mark Longair
fuente
gracias, pero esperaba que hubiera una forma más limpia de agregar esa extensión ... python incluso tiene una función de texto dividido para cortar la extensión ... así que tiene que haber algo para hacer lo contrario
Damon Julian
2
La función splitext retiene el '.' al frente de la extensión. Esta es probablemente la forma más limpia de hacerlo. Si desea que se "vea" más limpio en su código, le sugiero que use una función o una función lambda.
Vorticidad
0

Solo use os.path.joinpara unir su ruta con el nombre de archivo y la extensión. Use sys.argvpara acceder a los argumentos pasados ​​al script cuando lo ejecuta:

#!/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')

Simplemente ejecute el script como:

   # on windows-based systems
   python script.py year

   # on unix-based systems
   ./script.py year
Albert
fuente