[Python-es] Posible problema con copias de diccionarios

Christian Pinedo Zamalloa chr.pinedo en gmail.com
Jue Sep 9 10:20:34 CEST 2010


Muchas gracias a todos por la ayuda.

He probado el tema del dict.copy() y el resultado es el mismo.

Creo que como dice Chema el problema debe estar igual en algún
diccionario intermedio, pero no consigo ver nada (mis niveles de
Python son bastante básicos basta con ver mi código C-style...).
Adjunto todo el código de la función que me da los problemas para ver
si podéis ver algún error de bulto que esté cometiendo.

Como podéis ver en la salida de DEBUG, parece que los diccionarios se
copian bien pero cuando en cuanto modifico el diccionario copiado
newcall se borran los valores de las keys que no han sido modificadas
y que han sido copiadas de oldcall.

CODIGO
=======

 41 def parse_line(calls, keys, queue, line):
 42     newcall = {}
 43     for key in keys:
 44         newcall[key] = ''
 45     oldcall = {}
 46     id = line.split('|')[1]
 47     event = line.split('|')[4]
 48     # Comprobar si se debe procesar la línea porque afecta a la cola deseada
 49     # Si no es una línea de interés devolver la ejecución sin
modificar calls
 50     if queue != line.split('|')[2]:
 51         return
 52     # Comprobar si el ID de la línea coincide con un ID de la lista calls
 53     # En tal caso obtener la call de calls y eliminarla de calls
 54     for i in range(len(calls)):
 55         if calls[i]['id'] == id:
 56             if calls[i]['event'] == "ENTERQUEUE" or\
 57                calls[i]['event'] == "CONNECT":
 58                 print >> sys.stderr, "DEBUG. Bucle. oldcall
inicial.\n", oldcall
 59                 oldcall = calls[i].copy()
 60                 print >> sys.stderr, "DEBUG. Bucle. oldcall
copiado.\n", oldcall
 61                 calls.pop(i)
 62                 break
 63             else:
 64                 print >> sys.stderr, "Error: Se va a sobreescribir
un evento\
 65                 no considerado en el script %s" % call['event']
 66                 sys.exit(1)
 67     # Si se ha obtenido una call de calls modificar la futura
llamada con los
 68     # valores iniciales obtenidos.
 69     if oldcall:
 70         print >> sys.stderr, "DEBUG. oldcall definido. newcall
inicial.\n", newcall
 71         newcall = oldcall.copy()
 72         print >> sys.stderr, "DEBUG. oldcall definido. newcall
copiado.\n", newcall
 73     # Modificar la nueva llamada a insertar en la lista calls
 74     if event == "ENTERQUEUE":
 75         newcall['date'] = line.split('|')[0]
 76         newcall['id'] = line.split('|')[1]
 77         newcall['queue'] = line.split('|')[2]
 78         newcall['event'] = line.split('|')[4]
 79         newcall['callerid'] = line.split('|')[5]
 80     elif event == "CONNECT":
 81         newcall['event'] = line.split('|')[4]
 82         newcall['agent'] = line.split('|')[3].split('@')[0].split('/')[1]
 83         newcall['waittime'] = line.split('|')[5]
 84     elif event == "COMPLETEAGENT" or event == "COMPLETECALLER":
 85         newcall['event'] = "COMPLETE"
 86         newcall['calltime'] = line.split('|')[6]
 87     elif event == "ABANDON":
 88         newcall['event'] = line.split('|')[4]
 89         newcall['outposition'] = line.split('|')[5]
 90         newcall['inposition'] = line.split('|')[6]
 91         newcall['waittime'] = line.split('|')[7]
 92     elif event == "TRANSFER" or event == "SYSCOMPAT" or event ==
"EXITEMPTY"\
 93          or event == "EXITWITHKEY" or event == "EXITWITHTIMEOUT":
 94         print >> sys.stderr, "Error: Se va a insertar un evento\
 95         no considerado en el script %s" % event
 96         sys.exit(1)
 97     else:
 98         return
 99     print >> sys.stderr, "DEBUG. newcall modificado.\n", newcall
100     # Insertar la nueva llamada call en la lista calls
101     calls.append(newcall)
102     return


DEBUG

DEBUG. Bucle. oldcall inicial.
{}
DEBUG. Bucle. oldcall copiado.
{'queue': '17810', 'callerid': '', 'calltime': '', 'agent': '', 'id':
'1283942742.31886', 'waittime': '', 'inposition': '', 'outposition':
'', 'date': '1283942754', 'event': 'ENTERQUEUE'}
DEBUG. oldcall definido. newcall inicial.
{'waittime': '', 'callerid': '', 'calltime': '', 'agent': '', 'event':
'', 'queue': '', 'inposition': '', 'outposition': '', 'date': '',
'id': ''}
DEBUG. oldcall definido. newcall copiado.
{'waittime': '', 'callerid': '', 'calltime': '', 'agent': '', 'event':
'ENTERQUEUE', 'queue': '17810', 'inposition': '', 'outposition': '',
'date': '1283942754', 'id': '1283942742.31886'}
DEBUG. newcall modificado.
{'waittime': '1', 'callerid': '', 'calltime': '', 'agent': '',
'event': 'ABANDON', 'queue': '', 'inposition': '1', 'outposition':
'1', 'date': '', 'id': ''}


El día 9 de septiembre de 2010 02:16, Chema Cortes <py en ch3m4.org> escribió:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> El 08/09/10 20:13, Christian Pinedo Zamalloa escribió:
>> Hola,
>>
>> llevo más de 2 horas con un problema en Python que no consigo
>> solucionar y lo que es peor no consigo ver donde se encuentra el
>> problema. Explico el problema.
>>
>> Dentro del bucle for, en una lista de diccionarios compruebo si está
>> un diccionario que tengan una key de nombre id con un valor
>> determinado. Si se encuentra se copia el diccionario y se elimina de
>> la lista. Posteriormente este diccionario es copiado a otro
>> diccionario y sobre este nuevo diccionario se aplican cambios. Pues
>> bien al aplicarse cambios en unas keys se pierden los valores de la
>> copia... Creo que puede ser un problema con la eliminación del
>> diccionario de la lista o las copias de diccionarios que hago.... pero
>> he intentado mil cosas y no he conseguido nada.
>>
>> Pego el código y el resultado de las pruebas. Gracias!!
>
> Ni el código ni el resultado que has añadido sirven para esclarecer
> nada. Falta saber cómo defines la lista de diccionarios así como el
> resto de diccionarios intermedios.
>
> En el único sitio que veo que puedas tener acoples sería con la lista de
> diccionarios "calls"; pero apostaría a que el problema lo tienes por no
> inicializar bien algunos de los diccionarios intermedios.
>
> Ayudaría una reescritura del código que evite inicializar variables
> intermedias. Por ejemplo:
>
> oldcalls=[c for c in calls if c['id']==id]
>
> if any(c for c in oldcalls
>         if c['event'] not in ("ENTERQUEUE","CONNECT")):
>  print >> sys.stderr, "Error: ..."
>  sys.exit(1)
>
> if oldcalls:
>  newcall=oldcalls[0]
>  calls.remove(newcall)
> else:
>  newcall=dict( event = line.split('|')[4],
>                agent = line.split('|')[3].split('@')[0].split('/')[1],
>                waittime = line.split('|')[5],
>                ...
>           )
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iQEcBAEBAgAGBQJMiCdSAAoJEFdWyBWwhL4FpswIAK89XqGbBF1vRUE73TD+EzqW
> XwM9ZF1Heotf4Nz0bBOCigibfNME4BpEHxoYCxVExPdnySBqtc3Nlf1aVUDI+EYP
> pghWv4aRC6A+cmvgHPpucFGsuOwc5fZwLovvtXrc9L0n4eGoNGjYnv6kFdtGJArx
> IJfcdaGBviU0+B/iy79ewT+aalg1yT1y8XpW1USam3ZWPZfakQNlEp72ZHZrvY6U
> cRf6wx7T+Aj9Vu9iiMyLowxrcpOjlSF8mgLfC4IBVDWASVLc1THaDdOATbOVyLm4
> 45TCiAy0pMQU/QujinqyYWUmZGww88H4GNGARzAgLpCF3Lf7FzJOuzbXLVABt+4=
> =xFM7
> -----END PGP SIGNATURE-----
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/
>



-- 
Christian Pinedo Zamalloa (zako)
PGP keyID: 0x828D0C80
Fingerprint: 7BFF 4105 F46B 7977 BD96  348C 1007 4FF8 828D 0C80


Más información sobre la lista de distribución Python-es