Cómo ordenar una lista de diccionarios en python [RESUELTO]

Se tiene una lista de diccionarios Python, se quiere ordenar según un criterio ordenado de valores que puede tomar un determinada llave de un diccionario. Veámoslo con un ejemplo

Se tiene la siguiente lista de diccionarios:

[{'foo': FOO1}, {'foo': FOO2}, {'foo': FOO10}]

Y se tiene la siguiente lista de criterio de ordenación:

[FOO10, FOO2, FOO1]

Se espera que la lista resultante esté ordenada de la siguiente manera:

[{'foo': FOO10}, {'foo': FOO2}, {'foo': FOO1}]

Veamos cómo hacerlo

>>> to_sort = [{'foo': FOO1}, {'foo': FOO2}, {'foo': FOO10}]
>>> criteria = [FOO10, FOO2, FOO1]
>>> to_sort.sort(key=lambda x: criteria.index(x['foo']))
>>> to_sort
[{'foo': FOO10}, {'foo': FOO2}, {'foo': FOO1}]

Python: truncate string to n words [SOLVED]

A friend of mine asked how to implement a python function to truncate a string to the first n words. Easy!

def truncate_string(mystring, numberofwords):
    return ' '.join(mystring.split()[:numberofwords])

An example of use:

>>> sample_string = "hello world this is a string"
>>> print truncate_string(sample_string,2)
hello world

Python with MySQL special characters issues (tildes, etc) [SOLVED]

Some days ago a friend of mine who is learning python asked for my help. He was experimenting issues with spanish special characters (such as tildes -á,é,í,ó,ú- and -ñ-) when retrieving data from a MySQL database.

When I looked at the code, I saw he was connecting to MySQL using MySQLdb connect function as in:

import MySQLdb as mdb
con = mdb.connect(host='localhost',user='myuser',passwd='mypassword',db='mydatabase')

And he was astonished because I was able to solve his problems just by changing that to:

import MySQLdb as mdb
con = mdb.connect(host='localhost',user='myuser',passwd='mypassword',db='mydatabase', charset='utf8', use_unicode=False)

So don’t underestimate the power of official documentation and please, RTFM!

CentOS Python crash after update: Urandom [SOLVED]

We updated our CentOS machines and when we restarted our Apache servers, and tried to access the sites, a “500 Internal Server Error” was being shown.

We noticed some ugly shit in Apache error.log:

ImportError: cannot import name urandom
[Tue Nov 27 11:45:17 2012] [error] make_obcallback: Python path being used "['/usr/lib64/python2.4/site-packages/setuptools-0.6c5-py2.4.egg', '/usr/lib64/python2.4/site-packages/rdflib-2.4.0-py2.4-linux-x86_64.egg', '/usr/lib64/python2.4/site-packages/cx_Oracle-5.0-py2.4-linux-x86_64.egg', '/usr/lib64/python2.4/site-packages/MySQL_python-1.2.2-py2.4-linux-x86_64.egg', '/usr/lib/python2.4/site-packages/pylint-0.18.1-py2.4.egg', '/usr/lib/python2.4/site-packages/logilab_astng-0.19.1-py2.4.egg', '/usr/lib/python2.4/site-packages/logilab_common-0.44.0-py2.4.egg', '/usr/lib/python2.4/site-packages/pysnmp_apps-0.2.9a-py2.4.egg', '/usr/lib/python2.4/site-packages/pysnmp-4.1.13a-py2.4.egg', '/usr/lib/python2.4/site-packages/pyasn1-0.0.11a-py2.4.egg', '/usr/lib64/python24.zip', '/usr/lib64/python2.4', '/usr/lib64/python2.4/plat-linux2', '/usr/lib64/python2.4/lib-tk', '/usr/lib64/python2.4/lib-dynload', '/usr/lib64/python2.4/site-packages', '/usr/lib64/python2.4/site-packages/Numeric', '/usr/lib64/python2.4/site-packages/gtk-2.0', '/usr/lib/python2.4/site-packages']".
[Tue Nov 27 11:45:17 2012] [error] get_interpreter: no interpreter callback found.

To fix this, you must check the following:

[root@aneto ~]# rpm -q mod_python
mod_python-3.2.8-3.1
[root@aneto ~]# rpm -q httpd
httpd-2.2.3-65.el5_8.3
[root@aneto ~]# rpm -q python
python-2.4.3-46.el5_8.2

If the output is like the one above, then run:

[root@aneto ~]# yum downgrade python python-libs

And then restart Apache. Issues should be now fixed.

Recorrer una lista y eliminar elementos en Python (resuelto)

Hay veces que Python hace cosas que no te esperas.

Por ejemplo, si quieres recorrer e ir borrando los elementos de una lista según éstos se van recorriendo, pensarías que lo normal es hacerlo del siguiente modo. Pero fíjate lo que pasa:

>>> list = range(10)
>>> for x in list:
...     list.remove(x)
>>> list
[1, 3, 5, 7, 9]

La implementación que hace del recorrido tiene alguna historieta con los índices. Si queremos ir recorriendo y eliminando una lista en Python, la forma “correcta” de hacerlo es:

>>> list = range(10)
>>> for x in list[:]:
...     list.remove(x)
>>> list
[]

Python quick tip: remove duplicates from list [SOLVED]

Python makes some tasks easy. For instance, removing duplicate elements from a list can be done like:

>>> myList = [1, 2, 3, 3, 2, 2, 4, 5, 5]
>>> myList
[1, 2, 3, 3, 2, 2, 4, 5, 5]
>>> myList = list(set(myList))
>>> myList
[1, 2, 3, 4, 5]
>>>

Cheers to python! 🙂

Save python os.system output (stdout) in variable [SOLVED]

If you try something like this in python:

a = os.system("find / -name myfile.ext")
print a
 
# the output for find will be printed, but 'a' will store the exit code of the find command

So, how do you save the output of os.system to a variable? Use the subprocess module and proceed like:

>>> import subprocess
>>> command = "find / -name myfile.ext"
>>> proc = subprocess.Popen(command,stdout=subprocess.PIPE,shell=True)
>>> (out, err) = proc.communicate()
>>> outwithoutreturn = out.rstrip('\n')
>>> print out
./myfile.ext
 
>>> print outwithoutreturn
>>> ./mifile.ext
>>>

CDS-Invenio: List DELETED RECORDS from collection name – python script

Some time ago I posted some cds invenio mysql useful queries. Some people wrote some days ago asking wether I could put this into a function. Here you are 😉

List all deleted records which belong(ed) to collection ‘colname’ (tested with Invenio 0.99.x)

def listDeletedFromCollname(colname, coltag='980__c'):
  from invenio.dbquery import run_sql
  query = """ SELECT distinct bibrec_bib98x.id_bibrec 
              FROM bib98x, bibrec_bib98x
              WHERE bib98x.tag='%s' AND bib98x.value = '%s' AND bib98x.id = bibrec_bib98x.id_bibxxx       
                    AND bibrec_bib98x.id_bibrec IN (SELECT DISTINCT bibrec_bib98x.id_bibrec 
                                      FROM bibrec_bib98x, bib98x 
                                      WHERE bibrec_bib98x.id_bibxxx=bib98x.id AND
                                            bib98x.tag = '980__c' AND
                                            bib98x.value = 'DELETED') """ %(coltag,colname)
  res = run_sql(query)
  deletedlist = []
  for i in res:
    deletedlist.append(i[0])
  return deletedlist

And it is used like:

# list deleted records from a collecion defined by the query '980__c:FH'
a = listDeletedFromCollname('FH')
print a
 
# if I have my collection defined in another way, for instance using this query: '980__a:TAZ'
a = listDeletedFromCollname('TAZ','980__a')
print a

In a similar fashion we can list the ones that have NOT been deleted, as in:

def listNotDeletedFromCollname(colname, coltag='980__c'):
  from invenio.dbquery import run_sql
  query = """ SELECT distinct bibrec_bib98x.id_bibrec 
              FROM bib98x, bibrec_bib98x
              WHERE bib98x.tag='%s' AND bib98x.value = '%s' AND bib98x.id = bibrec_bib98x.id_bibxxx       
                    AND bibrec_bib98x.id_bibrec NOT IN (SELECT DISTINCT bibrec_bib98x.id_bibrec 
                                      FROM bibrec_bib98x, bib98x 
                                      WHERE bibrec_bib98x.id_bibxxx=bib98x.id AND
                                            bib98x.tag = '980__c' AND
                                            bib98x.value = 'DELETED') """ %(coltag,colname)
  res = run_sql(query)
  notdeletedlist = []
  for i in res:
    notdeletedlist.append(i[0])
  return deletedlist

Hope it’s useful 🙂

Python: autocomplete names with tab key [solved]

I learned a python trick that saved me a lot of time when using the interpreter. Just wanted to share it with you.

>>> import rlcompleter, readline
>>> readline.parse_and_bind("tab:complete")

With the above lines you’ll have a unix-like autocomplete for functions. For instance, if you type

>>> import os
>>> os.

And then you press “TAB” the list of OS module functions will show up. Ain’t it AWESOME? :>