¿Por qué el string.format pad de Python con “\ x00”?

Quería rellenar una cadena con caracteres nulos (“\ x00”). Conozco muchas formas de hacer esto, así que no responda con alternativas. Lo que quiero saber es: ¿por qué la función string.format() Python no permite el relleno con nulos?

Casos de prueba:

 >>> "{0:\x01<10}".format("bbb") 'bbb\x01\x01\x01\x01\x01\x01\x01' 

Esto muestra que los caracteres escapados de hex funcionan en general.

 >>> "{0:\x00<10}".format("bbb") 'bbb ' 

Pero “\ x00” se convierte en un espacio (“\ x20”).

 >>> "{0:{1}>> "{0:{1}<10}".format("bbb",chr(0)) 'bbb ' 

Incluso intentando un par de otras maneras de hacerlo.

 >>> "bbb" + "\x00" * 7 'bbb\x00\x00\x00\x00\x00\x00\x00' 

Esto funciona, pero no usa string.format

 >>> spaces = "{0: >> nulls = "{0:\x00>> spaces == nulls True 

Python está claramente sustituyendo espacios ( chr(0x20) ) en lugar de nulos ( chr(0x00) ).

Debido a que el método string.format en Python2.7 es un puerto de respaldo de string.format de string.format . Python2.7 unicode es la cadena de Python 3, donde la cadena de Python2.7 son los bytes de Python3. Una cadena es el tipo incorrecto para express datos binarios en Python3. Usaría bytes que no tienen un método de formato. Entonces, realmente debería preguntarse por qué el método de format en la cadena está en 2.7 cuando debería haber estado solo en el tipo Unicode, ya que eso es lo que se convirtió en la cadena en Python3.

Supongo que la respuesta es que es demasiado conveniente tenerlo allí.

Como una cuestión relacionada por qué todavía no hay format en bytes

Al investigar el código fuente de Python 2.7, descubrí que el problema se encuentra en esta sección de ./Objects/stringlib/formatter.h , líneas 718-722 (en la versión 2.7.3):

 /* Write into that space. First the padding. */ p = fill_padding(STRINGLIB_STR(result), len, format->fill_char=='\0'?' ':format->fill_char, lpad, rpad); 

El problema es que se utiliza un carácter cero / nulo ( '\0' ) como predeterminado cuando no se especifica ningún carácter de relleno. Esto es para habilitar este comportamiento:

 >>> "{0:<10}".format("foo") 'foo ' 

Puede ser posible configurar format->fill_char = ' '; como valor predeterminado en parse_internal_render_format_spec() en ./Objects/stringlib/formatter.h:186 , pero hay algo de compatibilidad hacia atrás que verifica '\0' más adelante. En cualquier caso, mi curiosidad está satisfecha. Aceptaré la respuesta de otra persona si tiene más historia o una mejor explicación de por qué que esto.

La respuesta a la pregunta original es que se trataba de un error en Python.

Fue documentado como permitido, pero no lo fue. Se solucionó en 2014. Para Python 2, la solución apareció por primera vez en 2.7.7 o 2.7.8 (no estoy seguro de cómo decir cuál)

Emisión original rastreada.