Buen día.
Quería saber si alguien sabría como hacer para que el contenido de un txt (guardado previamente con la informacion de un diccionario), luego pueda cargarlo, volver a modificarlo y guardarlo nuevamente.
El guardado funciona correctamente, el problema sucede cuando cargo el texto, una vez cargado, todo lo que utilizaba el diccionario comienza a fallar.
Guardado:
file = open("./filename.txt", "w")
for key, value in datos.items():
file.write(str(key)+ ": " + str(value))
file.close()
file = open("./filename.txt", "r")
for linea in file.readlines():
#l = linea.replace("'"," ").replace("[","").replace("]","").replace(",","")
datos = str({linea})
Gracias de antemano
Hola @SlayerBur
La cuestión es que estás abriendo el archivo en modo escritura (w), pero este modo borrará todo el contenido que tenga el archivo de destino, por lo que si haces una lectura mucho después, verás que estará vacío.
Puedes hacer dos cosas. La primera es abrir y leer todo el archivo primero, pero ésto consume mucha memoria, por lo que sería útil sólo si no te importa desperciarla y también si es menos de la que está en uso. La segunda es leer línea por línea, modificarla y escribir o en la salida o en un archivo de salida diferente al que está abierto.
Recomiendo la segunda para la mayoría de casos. Incluso con la segunda opción, en caso de enviar el resultado en la salida, puedes combinar ese contenido con otros programas al estilo unix usando tuberías.
~ DtxdF
Cita de: DtxdF en 30 Mayo 2021, 23:56 PM
Hola @SlayerBur
La cuestión es que estás abriendo el archivo en modo escritura (w), pero este modo borrará todo el contenido que tenga el archivo de destino, por lo que si haces una lectura mucho después, verás que estará vacío.
Puedes hacer dos cosas. La primera es abrir y leer todo el archivo primero, pero ésto consume mucha memoria, por lo que sería útil sólo si no te importa desperciarla y también si es menos de la que está en uso. La segunda es leer línea por línea, modificarla y escribir o en la salida o en un archivo de salida diferente al que está abierto.
Recomiendo la segunda para la mayoría de casos. Incluso con la segunda opción, en caso de enviar el resultado en la salida, puedes combinar ese contenido con otros programas al estilo unix usando tuberías.
~ DtxdF
El problema no es el guardado, la idea es que remplace todo el contenido.
el problema es al cargar, que no se crea el diccionario.
la informacion se guarda asi:
Imagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']Texto: ['.doc', '.pdf', '.cfg']Videos: ['.mp4', '.avi', '.flv']Otros: []
lo que quiero es que esa informacion del .txt pase a ser un diccionario asi:
datos = {"Imagen":[".png",".NEF",".jpg", ".JPG"], "Texto":[".doc",".pdf",".cfg"], "Videos":[".mp4",".avi",".flv"], "Otros":[]}
#!/usr/local/bin/python3.7
import re
import pprint
filename = "filename.txt"
files = {}
with open(filename, "r") as fd:
for line in fd:
line = line.strip()
if not (line):
continue
tokens = re.split("(\w+: )+", line)
i = 0
while (i < len(tokens)-1):
name = tokens[i].strip()
if not name:
i += 1
continue
extensions = tokens[i+1].strip()
files[name] = re.sub("(\[|\])", "", extensions)
files[name] = [x.strip() for x in files[name].split(",")]
i += 2
pprint.pprint(files)
Resultado:
{'Imagen:': ["'.png'", "'.NEF'", "'.jpg'", "'.JPG'", "'.ao'"],
'Otros:': [''],
'Texto:': ["'.doc'", "'.pdf'", "'.cfg'"],
'Videos:': ["'.mp4'", "'.avi'", "'.flv'"]}
Faltaría eliminar las comillas simples, pero ya eso es más fácil, o simplemente no puedes incluirlo en filename.txt.
Espero te sirva.
~ DtxdF
partamos de la base que la sintaxis visible del guardado es un asco,no hay comas para separa los items o salto de línea en el .txt
hay muchas formas de hacerlo:
#-*- coding: utf -8 -*-
with open("filename.txt", ) as archivo:
cadena = archivo.read()
cadena=cadena.replace(']',']*').split('*')
datos = {}
for x in range(len(cadena)-1):
temp = cadena[x].split(':')
datos[temp[0]]= eval(temp[1])
y todo eso se podría evitar si guardas los datos como diccionario correctamente.
Cita de: DtxdF en 31 Mayo 2021, 00:34 AM
#!/usr/local/bin/python3.7
import re
import pprint
filename = "filename.txt"
files = {}
with open(filename, "r") as fd:
for line in fd:
line = line.strip()
if not (line):
continue
tokens = re.split("(\w+: )+", line)
i = 0
while (i < len(tokens)-1):
name = tokens[i].strip()
if not name:
i += 1
continue
extensions = tokens[i+1].strip()
files[name] = re.sub("(\[|\])", "", extensions)
files[name] = [x.strip() for x in files[name].split(",")]
i += 2
pprint.pprint(files)
Resultado:
{'Imagen:': ["'.png'", "'.NEF'", "'.jpg'", "'.JPG'", "'.ao'"],
'Otros:': [''],
'Texto:': ["'.doc'", "'.pdf'", "'.cfg'"],
'Videos:': ["'.mp4'", "'.avi'", "'.flv'"]}
Faltaría eliminar las comillas simples, pero ya eso es más fácil, o simplemente no puedes incluirlo en filename.txt.
Espero te sirva.
~ DtxdF
Tuve que hacer una pequeña modificacion pero ya quedo, gracias :D
Cita de: tincopasan en 31 Mayo 2021, 01:43 AM
partamos de la base que la sintaxis visible del guardado es un asco,no hay comas para separa los items o salto de línea en el .txt
hay muchas formas de hacerlo:
#-*- coding: utf -8 -*-
with open("filename.txt", ) as archivo:
cadena = archivo.read()
cadena=cadena.replace(']',']*').split('*')
datos = {}
for x in range(len(cadena)-1):
temp = cadena[x].split(':')
datos[temp[0]]= eval(temp[1])
y todo eso se podría evitar si guardas los datos como diccionario correctamente.
El problema con
eval(...) es que ejecuta código arbitrario. Por ejemplo:
CitarImagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']Texto: ['.doc', '.pdf', '.cfg']Videos: ['.mp4', '.avi', '.flv']Otros: [__import__("os").system("whoami")]
La saldría sería:
dtxdf
@SlayerBur
Sí, me había faltado agregar un pequeño trozo. Línea 26:
files[name] = [x.strip().replace("'", "") for x in files[name].split(",")]
El
replace(...).
Editado:
Por cierto, y siguiendo la recomendación de @tincopasan, es recomendable colocar nuevas líneas para que sea más fácil editarlo. Por suerte el script puede leer e interpretar de la misma manera lo siguiente:
Con nuevas líneas:Imagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']
Texto: ['.doc', '.pdf', '.cfg']
Videos: ['.mp4', '.avi', '.flv']
Otros: []
Sin nuevas líneas:Imagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']Texto: ['.doc', '.pdf', '.cfg']Videos: ['.mp4', '.avi', '.flv']Otros: []
La saldría sería la misma, y es más recomendable la primera opción para el que tiene que editar las extensiones.
~ DtxdF
DtxdF bueno supongamos que los archivos no son creados por él, sino sería muy tonto poner "código malicioso" se usal literal_eval de la biblioteca ast y listo, siguen siendo muchas menos líneas de código y bibliotecas para analizar el texto, etc.
Cita de: DtxdF en 1 Junio 2021, 02:10 AM
El problema con eval(...) es que ejecuta código arbitrario. Por ejemplo:
La saldría sería:
dtxdf
@SlayerBur
Sí, me había faltado agregar un pequeño trozo. Línea 26:
files[name] = [x.strip().replace("'", "") for x in files[name].split(",")]
El replace(...).
Editado:
Por cierto, y siguiendo la recomendación de @tincopasan, es recomendable colocar nuevas líneas para que sea más fácil editarlo. Por suerte el script puede leer e interpretar de la misma manera lo siguiente:
Con nuevas líneas:
Imagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']
Texto: ['.doc', '.pdf', '.cfg']
Videos: ['.mp4', '.avi', '.flv']
Otros: []
Sin nuevas líneas:
Imagen: ['.png', '.NEF', '.jpg', '.JPG', '.ao']Texto: ['.doc', '.pdf', '.cfg']Videos: ['.mp4', '.avi', '.flv']Otros: []
La saldría sería la misma, y es más recomendable la primera opción para el que tiene que editar las extensiones.
~ DtxdF
El codigo es creado mediante una inteface grafica, no seria necesario usar el txt.
Inclusive estoy pensando en publicar el codigo, para el que quiera usarle o modificarle :D