2009-02-12 16 views
25

En this other question, los votos muestran claramente que la función os.path.splitext es preferible a la simple manipulación de cadena .split('.')[-1]. ¿Alguien tiene un momento para explicar exactamente por qué es eso? ¿Es más rápido, o más preciso, o qué? Estoy dispuesto a aceptar que hay algo mejor al respecto, pero no puedo ver de inmediato qué podría ser. ¿Podría importar un módulo completo para hacer esto ser excesivo, al menos en casos simples?Beneficios de os.path.splitext sobre regular .split?

EDITAR: La especificidad del sistema operativo es una gran ganancia que no es inmediatamente obvia; pero incluso yo debería haber visto el caso "¿Qué pasa si no hay un punto"? Y gracias a todos por los comentarios generales sobre el uso de la biblioteca.

+5

Porque esto no es Perl y solo hay una forma de hacer las cosas. ;) –

Respuesta

29

Bueno, hay implementaciones separadas para sistemas operativos separados. Esto significa que si la lógica para extraer la extensión de un archivo difiere en Mac de la de Linux, esta distinción será manejada por esas cosas. No conozco ninguna distinción así que puede que no haya ninguna.


Editar: @Brian comentarios que un ejemplo como /directory.ext/file sería, por supuesto, no trabajar con un simple .split('.') llamada, y usted tendría que saber tanto que los directorios pueden utilizar extensiones, así como el hecho de que en algunas sistemas operativos, barra diagonal es un separador de directorio válido.

Esto solo enfatiza que el usa una rutina de biblioteca a menos que tenga una buena razón para no incluir parte de mi respuesta.

Gracias @Brian.


Además, cuando un archivo no tiene una extensión, debe crear lógica para manejar ese caso. ¿Y qué sucede si lo que intentas dividir es un nombre de directorio que termina con una barra diagonal inversa? Sin nombre de archivo ni extensión

La regla debería ser que a menos que tenga una razón específica para no usar una función de biblioteca que haga lo que desee, úselo. Esto evitará tener que mantener y corregir códigos que otros tienen soluciones perfectamente buenas.

+1

La distinción de plataforma es muy importante cuando se trata de rutas completas. por ejemplo, "./some.dir/file" obviamente necesita saber que los caracteres "/" son separadores de ruta para calcular la extensión correcta. split() daría ".dir/file" como la extensión. – Brian

+0

Creo que una adición útil sería enlaces a la fuente relevante: aquí está la [lógica de división genérica] (http://hg.python.org/cpython/file/5c8b6e03ebfe/Lib/genericpath.py#l78), que es utilizada por [posix-specific] (http://hg.python.org/cpython/file/5c8b6e03ebfe/Lib/posixpath.py#l103) y [nt-specific] (http://hg.python.org/cpython/file /5c8b6e03ebfe/Lib/ntpath.py#l294) funciones de división de extensiones. – Tony

0

En el comentario a la respuesta que proporciona esta solución:

"Si el archivo no tiene extensión Esto devuelve incorrectamente el nombre de archivo en lugar de una cadena vacía."

No todos los archivos tienen una extensión.

+0

no todos los archivos tienen un nombre base, pero splitext() prefiere ignorar el punto inicial. – SilentGhost

+0

porque en Unix un archivo con un punto inicial probablemente signifique que es un archivo oculto, no una sola extensión – hop

1

Un método claramente definido y documentado para obtener la extensión de archivo siempre sería preferible a la división de una cadena de cualquier manera, ya que ese método sería más frágil por varias razones.

Editar: Esto no es específico del idioma.

11

os.path.splitext manejará correctamente la situación donde el archivo no tiene extensión y devolverá una cadena vacía. .split devolverá el nombre del archivo.

1

La primera y más obvia diferencia es que la llamada dividida no tiene lógica predeterminada cuando no hay extensión.

Esto también se puede lograr con una expresión regular, para que se comporte como un 1 liner sin inclusiones adicionales, pero igual devuelva, cadena vacía si la extensión no está allí.

Además, la biblioteca de rutas puede manejar contextos diferentes para rutas que tienen diferentes separadores para carpetas.

6

Existen sistemas operativos que no usan '.' Como separador de extensiones.

(Notablemente, RISC OS, por convención, utiliza '/', ya que '' se utiliza allí como un separador de ruta.)

+0

Cierto, pero os.path.splitext() solo se divide en un período de acuerdo con los documentos de python, por lo que aún fallaría en Ese caso. – Jay

+2

Jay: esto sugiere que o el documento está equivocado o que no existe (¡aún hay!) Una implementación de Python para el sistema operativo RISC o sistemas similares. De cualquier manera, 'splitext' sería a prueba de futuro para tales cambios, mientras que el otro método no lo sería. –

+0

sugiero que el sistema operativo RISC no se ajusta en absoluto porque la pregunta era sobre "al menos en casos simples". – SilentGhost

2
  1. herramienta adecuada para el trabajo correcto
  2. Ya bien depurado y probado como parte de la biblioteca estándar de Python: no hay errores introducidos por errores en la versión enrollada a mano (por ejemplo, ¿qué pasa si no hay extensión, o el archivo es un archivo oculto en UNIX como '.bashrc', o hay varias extensiones?)
  3. Al estar diseñado para este propósito, la función tiene valores de retorno útiles (nombre base, ext) para el nombre de archivo pasado, que puede ser más útil en ciertos casos frente a tener que dividir la ruta manualmente (de nuevo, casos extremos podrían ser una preocupación cuando averiguar el nombre base - ext)

La única razón por la que preocuparse acerca de la importación del módulo es la preocupación por encima de la cabeza - que no es probable que ser una preocupación en la gran mayoría de los casos, y si es así de apretada, entonces es probable que otros gastos generales en Python supongan un problema mayor antes de eso.

10

splitext() hace una búsqueda inversa para '.' y devuelve la porción de extensión tan pronto como la encuentre. split('.') hará una búsqueda directa para todos '.' personajes y, por lo tanto, casi siempre es más lento. En otras palabras, splitext() está específicamente escrito para devolver la extensión a diferencia de split().

(consulte posixpath.py en la fuente de Python si desea examinar la implementación).

0

Además de ser estándar y, por tanto, garantiza que sea disponible, os.path.splitext:

maneja los casos de borde - como la de una extensión que falta.
Ofrece garantías - Además de devolver correctamente la extensión, si existe, garantiza que root + ext siempre devolverá la ruta completa.
Es multiplataforma - en la fuente de Python, en realidad hay tres versiones diferentes de os.path, y se llaman en función del sistema operativo en el que Python cree que se encuentra.
Es más legible - tenga en cuenta que su versión requiere que los usuarios sepan que los arreglos se pueden indexar con números negativos.

por cierto, no debería ser más rápido.

0

1) simple split ('.') [- 1] no funcionará correctamente para la ruta como C: \ foo.bar \ Makefile, por lo que primero debe extraer basename con os.path.basename(), e incluso en este caso no podrá dividir el archivo sin extensión correctamente. os.path.splitext haz esto debajo del capó.

2) A pesar de que os.path.splitext es una solución multiplataforma, no es ideal.Veamos los archivos especiales con punto inicial, p. .cvsignore, .bzrignore, .hgignore (son muy populares en algunos VCS como archivos especiales). os.path.splitext devolverá el nombre completo del archivo como extensión, aunque no me parece correcto. Porque en este caso, el nombre sin extensión es una cadena vacía. Aunque este es el comportamiento previsto de la biblioteca estándar de Python, es posible que no sea lo que realmente quiere el usuario.

0

no estoy seguro de Python ha sido portado a la plataforma VMS, pero suponiendo que lo hicieron (*):

  • Los nombres de archivo son típicamente del formato:. $ Dispositivo-dir-subdirectorio $ Nombre Tipo $; $ versión (**)

espero que te das cuenta de que el uso de un método de alcance restringido, que sólo se ve influenciada por los sistemas que está expuesto en adelante, no es óptimo para el mantenimiento de código largo plazo y tal las prácticas son particularmente perjudiciales para mezclar y combinar componentes de software dispares en proyectos de software más grandes s.

Esencialmente, en este último caso la probabilidad de éxito (fiabilidad) es similar a

R (t) = 1- (1-Ri)^n

y ahora se puede ver cómo las implementaciones de software pobres/incompletas resultan en programas defectuosos. En términos más generales, el software de portabilidad es difícil precisamente debido a dichos errores.

(*) hm, Google reveló rápidamente alrededor de: https://www.vmspython.org
(**) ¡Consulte las guerras de regex aquí! https://stackoverflow.com/a/4465456/1574494