¿Cómo puedo crear una ruta completa a un archivo a partir de partes (p. ej., ruta a la carpeta, nombre y extensión)?

6 minutos de lectura

Avatar de usuario de Damon Julian
Damon Julián

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, un nombre de archivo base y una cadena de formato de archivo?

El directorio puede o no existir en el 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 forma. Lo intenté os.path.join:

join(dir_name,base_filename,format)

pero da

/home/me/dev/my_reports/daily_report/pdf

Avatar de usuario de ʇsәɹoɈ
ʇsәɹoɈ

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 abarrotado de casos especiales para cada sistema operativo. No es necesario hacer esto para las “extensiones” de nombre de archivo (consulte la nota al pie) porque siempre están precedidas por un carácter de punto, en todos los sistemas operativos que las implementan.

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 su código limpio, simplemente incluya el punto en el sufijo:

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

Ese enfoque también resulta ser compatible con las convenciones de sufijos en rutalib, que se introdujo en python 3.4 unos años después de que se hiciera esta pregunta. El nuevo código que no requiere compatibilidad con versiones anteriores puede hacer esto:

suffix = '.pdf'
pathlib.PurePath(dir_name, base_filename + suffix)

Es posible que tenga la tentación de usar el más corto Path() en lugar de PurePath() si solo está manejando rutas para el sistema operativo local. Cuestionaría esa elección, dados los problemas multiplataforma detrás de la pregunta original.

Advertencia: no use pathlib’s with_suffix() para este propósito. Ese método corromperá base_filename si alguna vez contiene un punto.


Nota al pie: fuera de los sistemas operativos de Microsoft, no existe tal cosa como una “extensión” de nombre de archivo. Su presencia en Windows proviene de MS-DOS y FAT, que lo tomaron 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 una parte del nombre del archivo en todos los demás sistemas operativos modernos, donde no tiene un significado incorporado.

  • Usted mencionó que el separador del sistema operativo puede no ser .. Para esto se puede usar os.extsep.

    – sjbx

    18 de marzo de 2013 a las 14:25


  • No mencioné tal cosa.

    – ʇsәɹoɈ

    11/06/2013 a las 21:35

  • Hizo 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 es siempre un punto’. El OP también expresó que vieron /pdf al final. Así que podrías haberlo hecho os.path.join(dir_name, base_filename, os.extsep, extension). Tu respuesta es perfectamente correcta.

    – sjbx

    12/06/2013 a las 14:00

  • Sí, tienes razón, solo devuelve una cadena, así que os.path.join(dir_name, ”.join([base_filename, os.extsep, extension])) Deberías hacerlo. Nuevamente, no socava la exactitud de su respuesta.

    – sjbx

    14 de junio de 2013 a las 8:09


  • @sjbx deberías poner + entre las partes del nombre de archivo. os.path.join() agrega separadores de ruta específicos del sistema operativo (/ por ejemplo) entre los argumentos (como @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

    21 de junio de 2019 a las 14:54


Avatar de usuario de Eugene Yarmash
Eugene Yarmash

En Python 3.4 y superior, el pathlib módulo de biblioteca estándar se puede usar así:

>>> from pathlib import Path
>>> dirname="/home/reports"
>>> filename="daily"
>>> suffix = '.pdf'
>>> Path(dirname, filename).with_suffix(suffix)
PosixPath('/home/reports/daily.pdf')

  • Encuentro que pathlib es mucho más elegante que os.path.join, que parece bastante torpe en comparación.

    – pionero

    6 mayo 2019 a las 20:35

  • No funciona si su nombre de archivo tiene un “.” >>>filename2= ‘daily.hourly’ >>>Path(dirname, filename2).with_suffix(sufijo) Salida:WindowsPath(‘/home/reports/daily.pdf’)

    – me iré

    28 de junio de 2019 a las 6:27


  • @wontleave: si un nombre de archivo ya tiene un sufijo, with_suffix() lo sustituirá en lugar de agregarlo. quieres algo como Path(dirname, filename2 + suffix)

    – Eugene Yarmash

    28 de junio de 2019 a las 8:46

  • pathlib también ofrece una inteligente sobrecarga de operadores: (Path(dirname) / filename).with_suffix(suffix).

    – Karl Knechtel

    4 abr a las 1:50

Avatar de usuario de Mark Longair
marca longair

>>> import os
>>> os.path.join(dir_name, base_filename + "." + format)
'/home/me/dev/my_reports/daily_report.pdf'

  • gracias, pero esperaba que hubiera una forma más limpia de agregar esa extensión… python incluso tiene una función splitext para cortar la extensión… así que tiene que haber algo para hacer lo contrario

    – Damon Julián

    20 de agosto de 2011 a las 16:16

  • La función splitext conserva el ‘.’ en la parte delantera 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

    20 de agosto de 2011 a las 21:19

Avatar de usuario de Saltanat Khalyk
Saltanat Khalyk

¿Por qué no simplemente incluir la extensión en el nombre de archivo base?

dir_name="/home/me/dev/my_reports/"
base_filename="daily_report.pdf"
os.path.join(dir_name, base_filename)

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.

BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATE_PATH = Path.joinpath(BASE_DIR,"templates")
print(TEMPLATE_PATH)

Avatar de usuario de Karl Knechtel
Carlos Knechtel

import os
def createfile(name, location, extension):
    print(name, extension, location)
    #starting creating a file with some dummy contents
    path = os.path.join(location, name + '.' + extension)
    f = open(path, "a")
    f.write("Your contents!! or whatever you want to put inside this file.")
    f.close()
    print("File creation is successful!!")

def readfile(name, location, extension):
    #open and read the file after the appending:
    path = os.path.join(location, name + '.' + extension)
    f = open(path, "r")
    print(f.read())

#pass the parameters here
createfile('test','./','txt')
readfile('test','./','txt')

¿Ha sido útil esta solución?