[Python] ABM archivo de texto

Iniciado por horacio_b92, 4 Julio 2016, 01:51 AM

0 Miembros y 1 Visitante están viendo este tema.

horacio_b92

Buenas gente, necesito ayuda con un ABM de un archivo de bancos donde el mismo viene cada registro por linea y cada campo separado por coma, con los campos id, descripcion y si existe para poder hacer la baja logica. No me esta sobreescribiendo en la baja el registro donde estaba, alguna ayuda o otra forma de hacerlo?


class Bank:

    def __init__(self, id, description='', exist=1, pos=0):
        self.id = id
        self.description = description
        self.exist = exist
        self.pos = pos

    def __repr__(self):
        return "{0:4.4},{1:30.30},{2:1.1}\n".format(str(self.id), self.description, str(self.exist))


class Banks:

    def __init__(self, filename):
        self.filename = filename
        self.load()

    def upload_in_memory(self, f):
        length = 0
        for line in f.readlines():
            record = line.split(',')
            bank = Bank(int(record[0].replace('\x00', '').strip()))
            bank.description = record[1].strip()
            bank.exist = int(record[2].strip())
            bank.pos = length
            length += len(line)
            self.banks.append(bank)

    def load(self):
        self.banks = []
        try:
            f = open(self.filename, 'r')
            self.upload_in_memory(f)
        except IOError:
            return

    def exists(self, id):
        for bank in self.banks:
            if bank.id == id and bank.exist == 1:
                return True
        return False

    def save(self, id, description, exist, pos=0):
        bank = Bank(id, description, exist)
        if pos == 0:
            length = len(str(bank))
            position = (id * length) - length
        else:
            position = pos
        with open('maebancos.txt', 'a') as f:
            f.seek(position, 0)
            f.write(str(bank))

    def add(self, id):
        if not self.exists(id):
            description = raw_input("Descripcion: ")
            self.save(id, description, 1)
            print "{0} dado de alta con exito!!!".format(description)
            Menu.pause()
        else:
            print "El Banco ya ha sido dado de alta!!"
            Menu.pause()

    def search(self, id):
        for bank in self.banks:
            if bank.id == id:
                return bank

    def delete(self, id):
        if self.exists(id):
            bank = self.search(id)
            print "Codigo de banco: {0}\nDescripcion: {1}".format(bank.id, bank.description)
            opc = raw_input("Baja (B) Cancelar (C)").upper()
            if opc == 'B':
                self.save(bank.id, bank.description, 0, bank.pos)
                print "{0} dado de baja con exito!!".format(bank.description)
                Menu.pause()
        else:
            print "El banco no existe!!"
            Menu.pause()

    def update(self, id):
        if self.exists(id):
            bank = self.search(id)
            print "Codigo de banco: {0}\nDescripcion: {1}".format(bank.id, bank.description)
            print "Anote el nuevo dato"
            description = raw_input("Descripcion: ")
            self.save(bank.id, description, 1, bank.pos)
            print "{0} modificado con exito!!!".format(bank.description)
            Menu.pause()
        else:
            print "El banco no existe!!"
            Menu.pause()



class Menu:

    @staticmethod
    def pause():
        raw_input("Oprima una tecla para continuar")

    @staticmethod
    def input_code():
        while True:
            try:
                bank_code = int(raw_input("Codigo Banco: "))
                return bank_code
            except ValueError:
                print "Presta atencion, solo digitos!!"

    @staticmethod
    def menu():
        while True:
            prompt = "1) Alta de Banco\n2)Baja de Banco\n3)Modificacion de Banco\n"
            prompt += "Elija una opcion: "
            opc = int(raw_input(prompt))
            banks = Banks('maebancos.txt')
            if opc == 1:
                banks.add(Menu.input_code())
            elif opc == 2:
                banks.delete(Menu.input_code())
            elif opc == 3:
                banks.update(Menu.input_code())
            else:
                return



Menu.menu()


desde ya gracias, aclaro no puede usar base de datos lo tengo que hacer en archivo plano

peter_lyon

Hola, nos cuentas pocas cosas como para tener un conocimiento total del problema. Te indico cosas que veo:

Python es un lenguaje que permite programar de mil formas diferentes. El código que veo, me recuerda mucho a Java y la obsesión con hacer programación orientada a objetos pura, lo cual solo sirve para complicar el código y hacer los programas más grandes y aburridos.

Luego, veo que estás usando como estructura de datos para los bancos una lista: banks = [].
No se si conoces ya los diccionarios. Un diccionario permite almacenar datos mediante una clave, en vez de tenerlos todos en una lista "lineal".

El símbolo para declarar un diccionario vacío es: {}
Ejemplo:

self.banks = {}

De esta forma, como supongo que los "id" de los bancos serán únicos, puedes usar la propia "id" de un banco para obtenerlo, en vez de recorrer toda la lista hasta encontrarlo (método search).

Ejemplo:

def search(self, id):
  if id in self.banks:  return self.banks[id] # si existe lo devuelvo
  else: return None  # devuelvo None porque no existe


Te recomiendo que la función save, genere un archivo nuevo, borrando todo lo que hubiera con anterioridad. Es decir, volcando una copia de banks al archivo. Todo será mucho más simple.

No se si tienes restricciones a la hora de usar unas determinadas cosas, no se si te han dado ya un diseño de como tienes que hacerlo y te han quitado la libertad de hacerlo como tú quieras.

Dinos hasta dónde eres libre para hacerlo como tú quieres, y si tienes libertad entonces te haré un programa bien hecho, con la mitad de líneas o menos que funciona muy bien y es mucho más simple de entender y programar, que es la filosofía de python.
El diseño que tú has seguido es una Programación Orienta a Objetos clásica, muy noventera, pero estamos en 2015, eso ya no está de moda ;D



MCKSys Argentina

Un poco de humor:

Cita de: peter_lyon en  4 Julio 2016, 02:51 AM
El diseño que tú has seguido es una Programación Orienta a Objetos clásica, muy noventera, pero estamos en 2015, eso ya no está de moda ;D

2016. Estamos en el año 2016...  :xD :xD :xD

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


horacio_b92

#3
Cita de: peter_lyon en  4 Julio 2016, 02:51 AM
Hola, nos cuentas pocas cosas como para tener un conocimiento total del problema. Te indico cosas que veo:

Python es un lenguaje que permite programar de mil formas diferentes. El código que veo, me recuerda mucho a Java y la obsesión con hacer programación orientada a objetos pura, lo cual solo sirve para complicar el código y hacer los programas más grandes y aburridos.

Luego, veo que estás usando como estructura de datos para los bancos una lista: banks = [].
No se si conoces ya los diccionarios. Un diccionario permite almacenar datos mediante una clave, en vez de tenerlos todos en una lista "lineal".

El símbolo para declarar un diccionario vacío es: {}
Ejemplo:

self.banks = {}

De esta forma, como supongo que los "id" de los bancos serán únicos, puedes usar la propia "id" de un banco para obtenerlo, en vez de recorrer toda la lista hasta encontrarlo (método search).

Ejemplo:

def search(self, id):
  if id in self.banks:  return self.banks[id] # si existe lo devuelvo
  else: return None  # devuelvo None porque no existe


Te recomiendo que la función save, genere un archivo nuevo, borrando todo lo que hubiera con anterioridad. Es decir, volcando una copia de banks al archivo. Todo será mucho más simple.

No se si tienes restricciones a la hora de usar unas determinadas cosas, no se si te han dado ya un diseño de como tienes que hacerlo y te han quitado la libertad de hacerlo como tú quieras.

Dinos hasta dónde eres libre para hacerlo como tú quieres, y si tienes libertad entonces te haré un programa bien hecho, con la mitad de líneas o menos que funciona muy bien y es mucho más simple de entender y programar, que es la filosofía de python.
El diseño que tú has seguido es una Programación Orienta a Objetos clásica, muy noventera, pero estamos en 2015, eso ya no está de moda ;D






Hola no tengo ningún tipo de restricción para hacerlo, estoy aprendiendo así que si ves una mejor solución bienvenida sea. si conozco los diccionarios pero no lo habia pensado y seria mejor que usar clase. desde ya gracias por comentar




con respecto al problema es hacer un alta, baja, modificación o CRUD como quieras llamarle de banco con los atributos id y descripción.




Cita de: peter_lyon en  4 Julio 2016, 02:51 AM
Hola, nos cuentas pocas cosas como para tener un conocimiento total del problema. Te indico cosas que veo:

Python es un lenguaje que permite programar de mil formas diferentes. El código que veo, me recuerda mucho a Java y la obsesión con hacer programación orientada a objetos pura, lo cual solo sirve para complicar el código y hacer los programas más grandes y aburridos.

Luego, veo que estás usando como estructura de datos para los bancos una lista: banks = [].
No se si conoces ya los diccionarios. Un diccionario permite almacenar datos mediante una clave, en vez de tenerlos todos en una lista "lineal".

El símbolo para declarar un diccionario vacío es: {}
Ejemplo:

self.banks = {}

De esta forma, como supongo que los "id" de los bancos serán únicos, puedes usar la propia "id" de un banco para obtenerlo, en vez de recorrer toda la lista hasta encontrarlo (método search).

Ejemplo:

def search(self, id):
  if id in self.banks:  return self.banks[id] # si existe lo devuelvo
  else: return None  # devuelvo None porque no existe


Te recomiendo que la función save, genere un archivo nuevo, borrando todo lo que hubiera con anterioridad. Es decir, volcando una copia de banks al archivo. Todo será mucho más simple.

No se si tienes restricciones a la hora de usar unas determinadas cosas, no se si te han dado ya un diseño de como tienes que hacerlo y te han quitado la libertad de hacerlo como tú quieras.

Dinos hasta dónde eres libre para hacerlo como tú quieres, y si tienes libertad entonces te haré un programa bien hecho, con la mitad de líneas o menos que funciona muy bien y es mucho más simple de entender y programar, que es la filosofía de python.
El diseño que tú has seguido es una Programación Orienta a Objetos clásica, muy noventera, pero estamos en 2015, eso ya no está de moda ;D




Algo así, le hice los cambios que me sugeriste:
Código (python) [Seleccionar]

class Banks:

    def __init__(self, filename):
        self.filename = filename
        self.banks = {}
        self.load()

    def upload_in_memory(self, f):
        for line in f.readlines():
            record = line.split(',')
            id = record[0].strip()
            description = record[1].strip()
            self.banks[id] = description

    def load(self):
        try:
            f = open(self.filename, 'r')
            self.upload_in_memory(f)
        except IOError:
            return

    def search(self, id):
        if id in self.banks:
            return self.banks[id]
        return None

    def to_s(self, id, description):
        return "{0:4.4},{1:30.30}\n".format(id, description)

    def save(self):
        f = open('maebancos.txt', 'w')
        for key, value in self.banks.items():
            record = self.to_s(key, value)
            f.write(record)
        f.close()

    def add(self, id):
        bank = self.search(id)
        if not bank:
            description = raw_input("Descripcion: ")
            self.banks[id] = description
            self.save()
            print "{0} dado de alta con exito!!!".format(description)
            pause()
        else:
            print "El Banco ya ha sido dado de alta!!"
            pause()

    def delete(self, id):
        bank = self.search(id)
        if bank:
            print "Codigo de banco: {0}\nDescripcion: {1}".format(id, bank)
            opc = raw_input("Baja (B) Cancelar (C)").upper()
            if opc == 'B':
                del self.banks[id]
                self.save()
                print "{0} dado de baja con exito!!".format(bank)
                pause()
        else:
            print "El banco no existe!!"
            pause()

    def update(self, id):
        bank = self.search(id)
        if bank:
            print "Codigo de banco: {0}\nDescripcion: {1}".format(id, bank)
            print "Anote el nuevo dato"
            description = raw_input("Descripcion: ")
            self.banks[id] = description
            self.save()
            print "{0} modificado con exito!!!".format(bank)
            pause()
        else:
            print "El banco no existe!!"
            pause()


def pause():
    raw_input("Oprima una tecla para continuar")


def input_code():
    while True:
        try:
            bank_code = raw_input("Codigo Banco: ")
            return bank_code
        except ValueError:
            print "Presta atencion, solo digitos!!"

def menu():
    while True:
        prompt = "1) Alta de Banco\n2)Baja de Banco\n3)Modificacion de Banco\n4)Salir\n"
        prompt += "Elija una opcion: "
        opc = int(raw_input(prompt))
        banks = Banks('maebancos.txt')
        if opc == 1:
            banks.add(input_code())
        elif opc == 2:
            banks.delete(input_code())
        elif opc == 3:
            banks.update(input_code())
        elif opc == 4:
            return

menu()






Cita de: peter_lyon en  4 Julio 2016, 02:51 AM
Hola, nos cuentas pocas cosas como para tener un conocimiento total del problema. Te indico cosas que veo:

Python es un lenguaje que permite programar de mil formas diferentes. El código que veo, me recuerda mucho a Java y la obsesión con hacer programación orientada a objetos pura, lo cual solo sirve para complicar el código y hacer los programas más grandes y aburridos.

Luego, veo que estás usando como estructura de datos para los bancos una lista: banks = [].
No se si conoces ya los diccionarios. Un diccionario permite almacenar datos mediante una clave, en vez de tenerlos todos en una lista "lineal".

El símbolo para declarar un diccionario vacío es: {}
Ejemplo:

self.banks = {}

De esta forma, como supongo que los "id" de los bancos serán únicos, puedes usar la propia "id" de un banco para obtenerlo, en vez de recorrer toda la lista hasta encontrarlo (método search).

Ejemplo:

def search(self, id):
  if id in self.banks:  return self.banks[id] # si existe lo devuelvo
  else: return None  # devuelvo None porque no existe


Te recomiendo que la función save, genere un archivo nuevo, borrando todo lo que hubiera con anterioridad. Es decir, volcando una copia de banks al archivo. Todo será mucho más simple.

No se si tienes restricciones a la hora de usar unas determinadas cosas, no se si te han dado ya un diseño de como tienes que hacerlo y te han quitado la libertad de hacerlo como tú quieras.

Dinos hasta dónde eres libre para hacerlo como tú quieres, y si tienes libertad entonces te haré un programa bien hecho, con la mitad de líneas o menos que funciona muy bien y es mucho más simple de entender y programar, que es la filosofía de python.
El diseño que tú has seguido es una Programación Orienta a Objetos clásica, muy noventera, pero estamos en 2015, eso ya no está de moda ;D



dejo el codigo en:
https://github.com/horaciobelardita/ejercicios_programacion_I/blob/master/Ejercicio30_31/file.py
otra cosa ahora tendría que agregarle la posibilidad de agregar cuentas asociada con un banco, es decir, un banco tiene muchas cuentas, en otro archivo con los campos id_cuenta, id_banco, descripción_cuenta. como me conviene hacerlo si bien ahora las cuentas tienen un id único, uso diccionario con clave la id de cuenta y valores una lista con id_banco y descripción o conviene con objeto? desde ya gracias por la ayuda

Mod: no hagas doble post

peter_lyon

#4
Madre mía qué locura de código jajajaja

No entiendo como vuestros profesores os meten problemas tan grandes sin enseñaros primero cosas como un diccionario...

Parece que esto es igual en todos los sitios, enseñar poquito y mandar tareas muy complejas para que el alumno tarde muchas horas en hacer los trabajos...

Por lo que has subido a Github, veo que has avanzado mucho con el problema.
Un consejo, ya que no estás usando clases y usas contenedores genéricos de python como listas y diccionarios, puedes usar algún formato estándar como JSON o XML, para guardar los datos de una forma más simple, con esto hubieras ahorrado un buen rato de trabajo:


import json


def load_file(filename):
   with open(filename) as b:
       banks = json.load(b)

   
def save_to_file(filename):
   with open(filename, "wb") as b:
      json.dump(banks, b)




Por cierto, si algún día estás interesado en hacer este mismo "reto" pero de forma profesional, puedo enseñarte como hacerlo, verás que es mucho más fácil que como tú lo haces, pero hay que conocer las herramientas adecuadas.

MOD EDIT: No hacer doble post.

horacio_b92

Cita de: peter_lyon en  6 Julio 2016, 00:20 AM
Por cierto, si algún día estás interesado en hacer este mismo "reto" pero de forma profesional, puedo enseñarte como hacerlo, verás que es mucho más fácil que como tú lo haces, pero hay que conocer las herramientas adecuadas.

hola si bienvenido cualquier sugerencia para mejorar, me dejas tu correo por MP o como nos comunicamos para ensenarme? gracias y saludos

tincopasan

estaría bueno que peter_lyon si sabes un código mejor, lo publiques así todos podemos aprender.

peter_lyon

No os preocupéis, ahora mismo ando terminando un proyecto (es un programa python por cierto...), pero en unos días comienzo mis vacaciones.

Os haré un pequeño tutorial para hacer una aplicación con esas funcionalidades pero de forma profesional, con bases de datos, interfaz web con diseño responsive, diseño elegante, etc.

Las apps con interfaz de consola, están bien para aprender, pero nadie va a abrir un terminal para ejecutar una aplicación de este tipo.


horacio_b92

dale peter_lyon seria muy bueno, lo hago en terminal porque no es profesional ni comercial solo meramente académico. Tambien cuando puedas y si tenes ganas de explicar como podría hacer simplemente la creación, eliminación, modificación de en este caso por ejemplo Banco con su id, descripción usando objetos, validar que no se ingresen duplicados, ya sea almacenando en JSON o en txt. Gracias

peter_lyon

Es muy simple, tú por un lado vas a tener en memoria, tu diccionario de bancos(  banks = {} )

Cuando arranques la app cargas este diccionario del JSON, si es que este existe y tiene contenido, sino, banks = {}.

Cada vez que se altera tu diccionario en memoria, vuelves a volcarlo a JSON con la función que te dejé (save_to_file), que borra lo que hubiera antes en el fichero y lo actualiza con los nuevos contenidos.

De esta forma, si cada vez que alteres tu lista en memoria, haces un volcado nuevo a JSON con la función save_to_file, te olvidas del trabajo de estar buscando registros por el fichero y demás complicaciones.
Te dejo las 3 funciones que me pides, están escritas sobre la marcha, no las he probado pero supongo que si hay algún fallo será alguna tontería de sintaxis y sabrás arreglarlo.

Para añadir banco:

def add_banck(id, descipt):
 if id in banks:  return False # Ya existe, devolvemos false
 else:
   banks[id] = descript
   save_to_file("banks.json")
   return True # operacion completada con exito

para eliminar un banco:

def del_bank(id):
 if "id" in banks:
   del banks[id]
    save_to_file("banks.json")
   return True
 else: return False # No existe, no se puede borrar


para editar un banco:

def change_bank_descript(id, new_descript):
 if id in banks:
   banks[id].descript = new_descript
    save_to_file("banks.json")
   return True
 else:
   return False # no existe