[SOLUCIONADO] Python: Script de reemplazo, ayuda con los parámetros a pasar.

Iniciado por ezephp, Enero 08, 2016, 11:33:00 AM

Tema anterior - Siguiente tema

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

Hola que tal!

estuve aprendiendo un poco de python, y para practicar estoy haciendo un programa el cual tambien me viene bien.

El programa lo que hace basicamente es reemplazar un texto por otro en uno o varios archivos. La funcion ya la programe y esta andando bien, mi problema es pasar los parametros.

Necesito que el usuario por consola pase los parametros por ejemplo python No tienes permitido ver los links. Registrarse o Entrar a mi cuenta -a archivo -t typo -cnum 0 etc.

Se que suena basico, pero no lo logro hacer por completo., intente con un for a sys.argv pero funciona solo en parte, no me llega a servir, hay parametros q no son obligatorios.


gracias!

Puedes postear el script?
Yo tengo una manera un poco Dummy para hacer esto,entiendo que hay otro método con una librería cuyo nombre no recuerdo.

Yo utilizo el método getopt para este script, pero usualmente trabajo con sys.argv que me parece más práctico
las opciones en este ejemplo son arbitrarias: help, inpyut,output,code,telco.

las opciones que tienen ":" llevan un parámetro obligatorio. Ej,. -c no puede ser usado sin un valor, en cambio h, sí.
Código: python
    def __parseArgs(self,args):
        try:
            argumentsPassed,args = getopt.gnu_getopt(args,"hi:o:c:t:",)
        except getopt.GetoptError:
            self.err_msg(self.HELP_MESSAGE)
        try:
            if (len(argumentsPassed)):
                for option,value in argumentsPassed:
                    if option == "-i":
                        try:
                            self.__inputFile = open(value,'r')
                            ''' Crea el archivo default entrada + .sql'''
                            self.salida=value+".sql"
                        except Exception as e:
                            self.err_msg(e)
                    elif option=="-o":
                        self.salida=value
                    elif option=='-c':
                        self.__codArea=value
                    elif option=='-t':
                        self.id_telco=value
                    elif option=='-h':
                        print(self.HELP_MESSAGE)

        except UnboundLocalError as e:
            self.err_msg(e)



Saludos-

Po6xsecpo

tengo una funcion de reemplazo de texto la cual funciona bien (comprobado), el tema es que a esa funcion le tengo que pasar los parametros.

Yo tenia algo asi programado pero no me funciona bien.

Código: php

def main():
try:     
  opts, args = getopt.getopt(sys.argv[1:], "ahps:")
except getopt.GetoptError:         
  print "Opcion no valida"                   
  sys.exit(2)


for opt in sys.argv:               
if opt in "-a":     
   archivo = sys.argv[2]         
elif opt in '-h':                 
   comienzo_num = int(sys.argv[4])     
elif opt in "-s":         
   print "usaste la s" 


no me sirve bien porque imaginemos que no pone el parametro -a, entonces comienzo_num ya no tendria el sys.argv en 4, lo tendria en 2. se entiende?

tu codigo lo trate de usar, pero no lo pude hacer funcionar bien, abajo de todo deberia llamar a la funcion __parseArgs con que argumentos?

saludos y gracias

Enero 08, 2016, 02:56:12 PM #3 Ultima modificación: Enero 08, 2016, 03:01:01 PM por po6xsecpo
Esta línea te devuelve parejas una lista "opts" que tiene las respectivas tuplas "opción/valor"
Código: python
  opts, args = getopt.getopt(sys.argv[1:], "ahps:")

En este caso ya NO dependes del acceso posicional del tipo sys.argv[Y]  que es precisamente lo que hace a tu script fallar.


En mi caso el parámetro "args" de la función es precisamente el que usas tú "sys.argv[1:]", sólo que yo lo paso al llamar a la función porque es mi estilo para programar y lo uso para evitar usar una posición que el usuario no haya pasado. EJ. int(sys.argv[4])

En conclusión si una opción/valor están presentes esta parte de mi código de ejemplo te las tendrá mapeadas para poder iterar y evitar el traceback "indexOut" que probablemente estés teniendo,

Código: Python
for option,value in argumentsPassed:





**MODIFICANDO TU CÓDIGO**

Código: Python
for opt,val in opts:               
if opt in "-a":     
   archivo = val         
elif opt in '-h':                 
   comienzo_num = val     
elif opt in "-s":         
   print "usaste la s" 

entendi la logica, lo q haces es separar el parametro del valor que tiene, como el foreach en php, bien..., el tema es que me tira un error:

Código: php
    for opt,val in opts:               
NameError: name 'opts' is not defined


como que no esta definida, pero la variable opts yo la uso y la asgino en anteriores lineas asi:

Código: php
  opts, args = getopt.getopt(sys.argv[1:], "ahps:")


entonces que me faltaria para poder definirla??


gracias!


perfecto, me funciono, pero ahora me tira otro error...

te pongo el codigo completo de como quedo todo...

Código: python
def main():
try:     
  opts, args = getopt.getopt(sys.argv[1:], "a:cn:fn:t:b:r")

  for opt,val in opts:               
        if opt in "-a":     
           archivo      = val   
        elif opt in '-cn':                 
           comienzo_num = int(val)
        elif opt in "-fn":         
   final_num = int(val)
elif opt in '-t':
   tipo = "."+val
elif opt in '-b':
   texto_buscar = val
elif opt in '-r':
   texto_reemplazar = val

except getopt.GetoptError:         
  print "Opcion no valida"                   
  sys.exit(2)



def reemplazar(archivo,tipo,texto_buscar,texto_reemplazar,comienzo_num=0,final_num=0):

#verificamos si es un entero, si lo es quiere decir q hay una lista de archivos (array)
if comienzo_num != 0 and final_num != 0:

array = range(comienzo_num,final_num+1)
#print type(array) - resultado: list
else:
array = ''

#verificamos si es un array o no, para saber si son varios archivos o solo uno, un array se compone por archivo1,archivo2, etc, y uno solo es archivo.txt
if type(array) == list:
for numero in array:
archivo_completo = archivo+str(numero)+tipo

#verificamos que el archivo existe
if os.path.exists(archivo_completo) == True:
print "El archivo "+archivo_completo+" se reemplazo con exito"
for line in fileinput.input(archivo_completo, inplace=1):
if texto_buscar in line:
    line = line.replace(texto_buscar,texto_reemplazar)
sys.stdout.write(line)

else:
print "El archivo "+archivo_completo+" NO existe. Verificalo y volve a intentar."
else:
archivo_completo = archivo+tipo

#verificamos que el archivo existe
if os.path.exists(archivo_completo) == True:
for line in fileinput.input(archivo_completo, inplace=1):
if texto_buscar in line:
    line = line.replace(texto_buscar,texto_reemplazar)
sys.stdout.write(line)
print "El archivo se reemplazo con exito"

else:
print "El archivo "+archivo_completo+" NO existe. Verificalo y volve a intentar."

reemplazar(archivo,tipo,texto_buscar,texto_reemplazar,comienzo_num,final_num)


if __name__ == "__main__":
main()



y me tira este error:

line 99, in <module>
    reemplazar(archivo,tipo,texto_buscar,texto_reemplazar,comienzo_num,final_num)
NameError: name 'archivo' is not defined


Dice que no esta definida la variable archivo, pero yo le estoy pasando el parametro -a se supone que se tiene q definir


y otra consulta, en el main yo puse elif, me genera duda si solo es IF o es ELIF, me parece que iria IF solo ya que si se cumple el primer parametro no pasa al segundo no?

gracias!

El uso de elif es correcto, recuerda que si el user no mete la opción "a" igual necesitas checar si metió la "cn".

En este caso es por el "scope" (alcance de la variable) archivo. Como la declaras en main, de algna manera el resto del programa "NO la conoce". En el caso de reemplazar_archivo como le pasas algo llamado "archivo" esa referencia es local y solo es conocida dentro de ese contexto> la función reemplazar_archivo.

En este caso tienes 2 workarrounds:

1. Invocar reemplazar_archivo desde el main, donde sí se conoce el valor de "archivo" que deseas usar

2. Definir una variable "archivo" como None o como "" al inicio de tu script para que sea global a todo el script y puedas seguir llamando la función como lo haces.

Finalmente, te recomiendo estudiar el scope de variables en python (o cualquier lenguaje) y que bueno que estés probando las soluciones.

Saludos.
po6xsecpo

Estuve viendo, leyendo. Pero no logro solucionarlo.

Por logica y por lo que lei, obviamente las variables asignadas estan en LOCAL en la funcion main, por eso la funcion "reemplazar" no toma las variables. Creo que hasta ahi bien.

Entonces intente varias cosas..., algunas de ellas, ponerla como global afuera de todo, y despues que se asigne en main para que lo tome la funcion reemplazar. No me funciono, tambien intente ponerla como global dentro de la funcion reemplazar, y algunas cosas mas intente..

El tema es que me tira siempre error, evidentemente me falta algo y no me doy cuenta que,  por logica deberia poner las variables globales, pero en la practica no lo logro


espero tu respuesta

gracias!

Hola brother, en Python no es recomendable usar variables globales. La solución en este caso sería llamar a la función reemplazar desde la función main ya que ahí tienes todas las variables definidas.

Como observación, ya que estás comenzando con Python te recomiendo que tengas algo de cuidado con la sintaxis. En especial a la hora de tabular nunca mezcles espacios con tabuladores.

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

gracias once!

buen consejo lo de tabular, estoy acostumbrado a otros lenguajes como php que no importa tanto la tabulacion jaja.

estoy intentando de llamar a la funcion dentro de main, por un lado se me soluciono algunos errores, y por otro lado me genero errores, tiro el codigo de ahora...

Código: python
#!/usr/bin/env python3

print "-"*73
print "            A.R.T.A - Automatizar Reemplazo de Textos en Archivos |"
print " |"
print " Uso: ARTA.py archivo 1 5 txt texto_buscar texto_reemplazar |"
print " |"
print " Archivo   = nombre de archivo - Obligatorio |"
print " 1   = comienzo numero de archivo - OPCIONAL |"
print " 5   = final numero de archivo - OPCIONAL |"
print " txt   = tipo de archivo, eg: doc,txt,etc - Obligatorio |"
print " texto_buscar   = texto que quieres buscar para reemplazar |"
print " texto_reemplazar = texto que quieres reemplazar por el texto viejo |"
print " |"
print " En este caso reemplazariamos los archivo1.txt,etc,archivo5.txt  |"
print " |"
print " Pablo La Rocca     |"
print "-"*73

import os.path
import fileinput
import sys
import getopt


def main():
try:     
  opts, args = getopt.getopt(sys.argv[1:], "a:cn:fn:t:b:r")

  comienzo_num = 0
  final_num = 0


  for opt,val in opts:               
        if opt in "-a":     
           archivo      = val   
        elif opt in '-cn':                 
           comienzo_num = int(val)
        elif opt in "-fn":         
   final_num = int(val)
elif opt in '-t':
   tipo = "."+val
elif opt in '-b':
   texto_buscar = val
elif opt in '-r':
   texto_reemplazar = val

  reemplazar(archivo,tipo,texto_buscar,texto_reemplazar,comienzo_num,final_num)

except getopt.GetoptError:         
  print "Opcion no valida"                   
  sys.exit(2)




def reemplazar(archivo,tipo,texto_buscar,texto_reemplazar,comienzo_num=0,final_num=0):

#verificamos si es un entero, si lo es quiere decir q hay una lista de archivos (array)
if comienzo_num != 0 and final_num != 0:

array = range(comienzo_num,final_num+1)
#print type(array) - resultado: list
else:
array = ''

#verificamos si es un array o no, para saber si son varios archivos o solo uno, un array se compone por archivo1,archivo2, etc, y uno solo es archivo.txt
if type(array) == list:
for numero in array:
archivo_completo = archivo+str(numero)+tipo

#verificamos que el archivo existe
if os.path.exists(archivo_completo) == True:
print "El archivo "+archivo_completo+" se reemplazo con exito"
for line in fileinput.input(archivo_completo, inplace=1):
if texto_buscar in line:
    line = line.replace(texto_buscar,texto_reemplazar)
sys.stdout.write(line)

else:
print "El archivo "+archivo_completo+" NO existe. Verificalo y volve a intentar."
else:
archivo_completo = archivo+tipo

#verificamos que el archivo existe
if os.path.exists(archivo_completo) == True:
for line in fileinput.input(archivo_completo, inplace=1):
if texto_buscar in line:
    line = line.replace(texto_buscar,texto_reemplazar)
sys.stdout.write(line)
print "El archivo se reemplazo con exito"

else:
print "El archivo "+archivo_completo+" NO existe. Verificalo y volve a intentar."



if __name__ == "__main__":
main()


y me tira este error:

    comienzo_num    = int(val)
ValueError: invalid literal for int() with base 10: ''


Obviamente ahi dice el error, el tema es que no se porque lo tira, le estoy pasando de parametro un uno.


gracias!



Antes del for coloca:
Código: python
print opts
y coloca loq ue te sale. Así vemos que valores está tomando.

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Enero 12, 2016, 12:20:05 PM #12 Ultima modificación: Enero 12, 2016, 12:53:12 PM por ezephp
bueno, bien, solucione el problema anterior, la opcion -cn la tomaba por separado, osea tomaba -c sin valor y -n con el valor que le habia pasado, igual pasaba con -fn, asi que solo achique las opciones a q tuviera una sola letra, todavia nose porque funciona asi!, ahora quedo -c en ves de -cn y -f en ves de -fn.

Cual puede ser la causa?


gracias!

Hola, la verdad no estoy muy familiarizado con el módulo getopt pero en Python tienes el módulo argparse que te ayuda un poco con eso: Acá tienes una idea de como funciona

Código: python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-cn", help="Comienzo numero")
argumentos = parser.parse_args()

if argumentos.cn:
    print argumentos.cn


Y acá tienes la documentación por si quieres leer un poco más sobre el módulo No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta