2009-03-12 27 views
6

[Editar 2: Más información y depuración en respuesta ...]insertar datos en la base de datos de MS Access con ADO a través de Python

Estoy escribiendo un script en Python para exportar bases de datos de MS Access en una serie de textos archivos para permitir un control de versiones más significativo (lo sé, ¿por qué acceder? ¿Por qué no estoy usando soluciones existentes? Digamos que las restricciones no son de naturaleza técnica).

me ha exportado con éxito los contenidos y la estructura de la base de datos utilizando ADO y ADOX a través de la biblioteca comtypes completos, pero me estoy poniendo un problema volver a importar los datos.

Estoy exportar el contenido de cada tabla en un archivo de texto con una lista en cada línea, así:

[-9, u'No reply'] 
[1, u'My home is as clean and comfortable as I want'] 
[2, u'My home could be more clean or comfortable than it is'] 
[3, u'My home is not at all clean or comfortable'] 

Y la siguiente función para importar dicho fichero:

import os 
import sys 
import datetime 
import comtypes.client as client 
from ADOconsts import * 
from access_consts import * 

class Db: 
    def create_table_contents(self, verbosity = 0): 
     conn = client.CreateObject("ADODB.Connection") 
     rs = client.CreateObject("ADODB.Recordset") 
     conn.ConnectionString = self.new_con_string 
     conn.Open() 
     for fname in os.listdir(self.file_path): 
      if fname.startswith("Table_"): 
       tname = fname[6:-4] 
       if verbosity > 0: 
        print "Filling table %s." % tname 
       conn.Execute("DELETE * FROM [%s];" % tname) 
       rs.Open("SELECT * FROM [%s];" % tname, conn, 
         adOpenDynamic, adLockOptimistic) 
       f = open(self.file_path + os.path.sep + fname, "r") 
       data = f.readline() 
       print repr(data) 
       while data != '': 
        data = eval(data.strip()) 
        print data[0] 
        print rs.Fields.Count 
        rs.AddNew() 
        for i in range(rs.Fields.Count): 
         if verbosity > 1: 
          print "Into field %s (type %s) insert value %s." % (
           rs.Fields[i].Name, str(rs.Fields[i].Type), 
           data[i]) 
         rs.Fields[i].Value = data[i] 
        data = f.readline() 
        print repr(data) 
        rs.Update() 
       rs.Close() 
     conn.Close() 

Todo funciona bien excepto que los valores numéricos (doble e int) se insertan como ceros. ¿Alguna idea sobre si el problema está relacionado con mi código, eval, comtypes o ADO?

Editar: He solucionado el problema de insertar números: fundirlos como cadenas (!) Parece resolver el problema para los campos dobles y enteros.

Sin embargo, ahora tengo un problema diferente que previamente habían sido oscurecida por la anterior: el primer campo de cada fila se establece en 0, independientemente del tipo de datos ... ¿Alguna idea?

Respuesta

4

Y encontró una respuesta.

rs = client.CreateObject("ADODB.Recordset") 

necesita ser:

rs = client.CreateObject("ADODB.Recordset", dynamic=True) 

Ahora sólo tiene que mirar en qué. Solo espero que esta pregunta le ahorre a alguien unas horas ...

+0

Y el resto de la solución fue cambiar "rs.Fields [i] .Value = data [i]" a "rs.Fields [i] .Value = str (data [i])"? – BIBD

+0

No, no. Debería haber dicho explícitamente: al agregar el dinámico = Verdadero se resolvió tanto el problema original con valores numéricos, como el problema de seguimiento con resultados variables. Una vez que estuvo en su lugar, rs.Fields [i] .Value = data [i] funcionó bien y, de hecho, emitir los números como cadenas arrojó un error de desajuste de tipo. – mavnn

+0

Kewl, no estaba claro en la respuesta. En este punto, yo diría que marque su propia respuesta como Aceptada. – BIBD

0

¿Está tratando data[i] como una cadena? ¿Qué sucede si específicamente lo lanzas como int/double cuando configuras rs.Fields[i].Value?

Además, ¿qué sucede cuando imprime los contenidos de rs.Fields[i].Value después de establecerlos?

+0

Ver edición - Extrañamente Necesité específicamente lanzar de int/double a string para que funcione ... – mavnn

0

Aún no es una respuesta completa, pero parece ser un problema durante la actualización. He añadido algo de código de depuración más en el proceso de inserción que genera la siguiente (ejemplo de una sola fila proceso de actualización):

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [0, u'Blah', 55.0] 

El último valor en cada "insertado ..." línea es el resultado de la llamada rs.Fields [i] .Value antes de llamar a rs.Update(). La línea "Después ..." muestra los resultados de llamar a rs.Fields [i] .Value después de llamar a rs.Update().

Lo que es aún más molesto es que no falla de manera confiable. Volver a ejecutar el mismo código en el mismo registra unos minutos generaron más adelante:

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [1, u'Blah', 2.0] 

Como se puede ver, los resultados son fiables hasta que, entonces ... no cometerlos.

Cuestiones relacionadas