Barra invertida en Windows y barra diagonal en macOS y Linux

En Windows, las rutas se escriben utilizando barras invertidas (\) como separador entre los nombres de las carpetas. Los sistemas operativos macOS y Linux, sin embargo, utilizan la barra diagonal (/) como separador de rutas. Si quieres que tus programas funcionen en todos los sistemas operativos, tendrás que escribir tus scripts de Python para manejar ambos casos.

Afortunadamente, esto es sencillo de hacer con la función Path() del módulo pathlib. Si le pasas los valores de las cadenas de los nombres de los archivos y carpetas individuales de tu ruta, Path() devolverá una cadena con una ruta de archivos utilizando los separadores de ruta correctos. Introduzca lo siguiente en el shell interactivo:

>>> from pathlib import Path
>>> Path('spam', 'bacon', 'eggs')

WindowsPath('spam/bacon/eggs')
>>> str(Path('spam', 'bacon', 'eggs'))
'spam\\bacon\\eggs'

Obsérvese que la convención para importar pathlib es ejecutar from pathlib import Path, ya que de otro modo tendríamos que introducir pathlib.Path en todos los lugares donde aparezca Path en nuestro código. No sólo es tecleo extra, sino que también es redundante.

Estoy ejecutando los ejemplos del shell interactivo de este capítulo en Windows, así que Path('spam', 'bacon', 'eggs') devuelve un objeto WindowsPath para la ruta unida, representado como WindowsPath('spam/bacon/eggs'). Aunque Windows utiliza barras invertidas, la representación de WindowsPath en el intérprete de comandos interactivo las muestra utilizando barras invertidas, ya que los desarrolladores de software de código abierto han favorecido históricamente el sistema operativo Linux.

Si quiere obtener una cadena de texto simple de esta ruta, puede pasarla a la función str(), que en nuestro ejemplo devuelve 'spam\\bacon\\eggs'. (Observe que las barras invertidas se duplican porque cada barra invertida necesita ser escapada por otro carácter de barra invertida). Si hubiera llamado a esta función en, digamos, Linux, Path() habría devuelto un objeto PosixPath que, al pasarlo a str(), habría devuelto 'spam/bacon/eggs'. (POSIX es un conjunto de estándares para sistemas operativos tipo Unix, como Linux).

Estos objetos Path (en realidad, objetos WindowsPath o PosixPath, dependiendo de su sistema operativo) se pasarán a varias de las funciones relacionadas con archivos introducidas en este capítulo. Por ejemplo, el siguiente código une nombres de una lista de nombres de archivos al final del nombre de una carpeta:

>>> from pathlib import Path
>>> myFiles = ['accounts.txt', 'details.csv', 'invite.docx']
>>> for filename in myFiles:
        print(Path(r'C:\Users\Al', filename))
C:\Users\Al\accounts.txt
C:\Users\Al\details.csv
C:\Users\Al\invite.docx

En Windows, la barra invertida separa los directorios, por lo que no puede utilizarla en los nombres de archivo. Sin embargo, puede utilizar barras invertidas en los nombres de archivo en macOS y Linux. Así, mientras que Path(r'spam\eggs') se refiere a dos carpetas separadas (o a los archivos eggs en una carpeta spam) en Windows, el mismo comando se referiría a una sola carpeta (o archivo) llamada spam\eggs en macOS y Linux. Por esta razón, suele ser una buena idea utilizar siempre barras inclinadas en tu código Python (y así lo haré durante el resto de este capítulo). El módulo pathlib se asegurará de que siempre funcione en todos los sistemas operativos.

Ten en cuenta que pathlib fue introducido en Python 3.4 para reemplazar las antiguas funciones de os.path. Los módulos de la Biblioteca Estándar de Python lo soportan a partir de Python 3.6, pero si estás trabajando con versiones heredadas de Python 2, recomiendo usar pathlib2, que te da las características de pathlib en Python 2.7.

Uso del operador / para unir rutas

Normalmente utilizamos el operador + para sumar dos números enteros o de coma flotante, como en la expresión 2 + 2, que se evalúa al valor entero 4. Pero también podemos utilizar el operador + para concatenar dos valores de cadena, como la expresión 'Hello' + 'World', que se evalúa como el valor de cadena 'HelloWorld‘. Del mismo modo, el operador / que normalmente utilizamos para la división también puede combinar objetos Path y cadenas. Esto es útil para modificar un objeto Path después de haberlo creado con la función Path().

Por ejemplo, introduzca lo siguiente en el shell interactivo:

>>> from pathlib import Path
>>> Path('spam') / 'bacon' / 'eggs'
WindowsPath('spam/bacon/eggs')
>>> Path('spam') / Path('bacon/eggs')
WindowsPath('spam/bacon/eggs')
>>> Path('spam') / Path('bacon', 'eggs')
WindowsPath('spam/bacon/eggs')

El uso del operador / con objetos Path hace que la unión de rutas sea tan fácil como la concatenación de cadenas. También es más seguro que usar la concatenación de cadenas o el método join(), como hacemos en este ejemplo:

>>> homeFolder = r'C:\Users\Al'
>>> subFolder = 'spam'
>>> homeFolder + '\\' + subFolder
'C:\\Users\\Al\\spam'
>>> '\\'.join([homeFolder, subFolder])
'C:\\Users\\Al\\spam'

Un script que utilice este código no es seguro, porque sus barras invertidas sólo funcionarían en Windows. Podría añadir una sentencia if que compruebe sys.platform (que contiene una cadena que describe el sistema operativo del ordenador) para decidir qué tipo de barra invertida utilizar, pero aplicar este código personalizado en todos los lugares en los que se necesita puede ser inconsistente y propenso a errores.

El módulo pathlib resuelve estos problemas reutilizando el operador matemático de división / para unir rutas correctamente, independientemente del sistema operativo en el que se ejecute el código. El siguiente ejemplo utiliza esta estrategia para unir las mismas rutas que en el ejemplo anterior:

>>> homeFolder = Path('C:/Users/Al')
>>> subFolder = Path('spam')
>>> homeFolder / subFolder
WindowsPath('C:/Users/Al/spam')
>>> str(homeFolder / subFolder)
'C:\\Users\\Al\\spam'

Lo único que debes tener en cuenta al utilizar el operador / para unir rutas es que uno de los dos primeros valores debe ser un objeto Path. Python te dará un error si intentas introducir lo siguiente en el shell interactivo:

>>> 'spam' / 'bacon' / 'eggs'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'str'

Python evalúa el operador / de izquierda a derecha y evalúa a un objeto Path, por lo que el primer o segundo valor más a la izquierda debe ser un objeto Path para que la expresión completa se evalúe a un objeto Path. Así es como el operador / y un objeto Path se evalúan al objeto Path final.

Si ve el error TypeError: unsupported operand type(s) for /: 'str', necesita poner un objeto Path en el lado izquierdo de la expresión.

El operador / sustituye a la antigua función os.path.join(), de la que puede obtener más información en https://docs.python.org/3/library/os.path.html#os.path.join.

Deja una respuesta