Python et Btrieve 2 sur Windows : Accéder aux données Zen avec NoSQL
Actian Corporation
2 février 2018

Dans mon blog précédent ("Programming the Easy Way : Accessing a PSQL Zen Database with Python and ODBC"), j'ai montré comment accéder facilement à une base de données Actian Zen avec Python et ODBC. Mon projet suivant était d'utiliser la nouvelle fonctionnalité Btrieve 2 avec Python pour interfacer directement avec les fichiers de données sans utiliser de SQL.
Les clients de longue date de Btrieve/PSQL/Zen connaissent l'ancienne fonction Btrieve, une interface de programmation 3GL classique qui n'a pas vraiment changé depuis plus de 30 ans. Elle fournit un accès direct au moteur afin que vous puissiez manipuler les fichiers de données avec des options telles que Create, Open, Insert, Update, Delete, GetFirst, GetNext, GetEqual, etc. Désormais, avec Actian Zen v13, nous disposons de Btrieve 2, qui offre une interface orientée objet simplifiée et plus intuitive couvrant l'ensemble des appels Btrieve au moteur de base de données. Cette interface est destinée aux développeurs C/C++, mais nous fournissons également des fichiers SWIG (Simplified Wrapper & Interface Generator) afin que l'interface puisse être utilisée par les développeurs Python, Perl et PHP.
L'installation de Btrieve 2 avec Python nécessite quelques étapes :
- Préparez votre environnement Windows :
- Installer le moteur de base de données Actian Zen v13
- Installer Python pour Windows - j'ai utilisé la version 3.6 64-bit de python.org
- Téléchargez et décompressez Swig pour Windows - j'ai utilisé Swigwin-3.0.12 de swig.org
- Télécharger et décompresser le SDK Btrieve 2
- Visual Studio 2015 ou une version plus récente est également nécessaire ; vous pouvez installer une version communautaire de Microsoft si vous n'en avez pas déjà une à partir d'ici.
- Créez un dossier MyPrograms pour votre code Python , et copiez les fichiers suivants du SDK Btrieve 2 :
- btrieveCpp.lib & btrieveC.lib de win64
- btrieveC.h & btrieveCpp.h de include
- btrievePython.swig & btrieveSwig.swig from swig
- Ouvrez une invite de commande, placez-vous dans le dossier MyPrograms et entrez la commande suivante :
<swigwin_location>swig -c++ -D_WIN64 -python btrievePython.swig
Cela crée les fichiers suivants : btrievePython.py & btrievePython_wrap.cxx - Créez un fichier texte dans MyPrograms appelé setup.py contenant ce qui suit :
from distutils.core import setup, Extension btrievePython_module = Extension('_btrievePython', sources=['btrievePython_wrap.cxx'], library_dirs=['<MyPrograms location>'], libraries=['btrieveCpp'], ) setup (name='btrievePython', version='1.0', author='Actian', description="""Compile Btrieve 2 Python module""", ext_modules=[btrievePython_module], py_modules=["btrievePython"], )
- Dans une invite de commande, dans le dossier MyPrograms, exécutez cette commande pour construire le module btrievePython :
python setup.py build_ext --plat-name="win-amd64"
Cela crée le fichier Python compilé buildlib.win-amd64-3.6_btrievePython.cp36-win_amd64.pyd - Renommez le fichier .pyd en _btrievePython.pyd et copiez-le dans MyPrograms ou dans le dossier DLLs de votre installation Python .
Une fois ces étapes terminées, vous devriez pouvoir "importer btrievePython" dans un environnement ou un programme Python .
Une fois la bibliothèque d'importation btrievePython installée, vous êtes prêt à écrire des applications Btrieve 2 en Python! Voici un exemple qui effectue les mêmes opérations de base de données que la version ODBC de mon blog précédent - créer le même fichier, insérer des enregistrements et récupérer le nombre total inséré. Ce code est environ deux fois plus long que la version ODBC, mais il accède directement au fichier sans passer par la couche SQL. (Note : seul un contrôle d'erreur minimal a été inclus) :
import os import sys import struct import btrievePython as btrv btrieveFileName = "Test_Table.mkd" recordFormat = "<iB32sBBBH" recordLength = 42 keyFormat = "<i" # Create a session: btrieveClient = btrv.BtrieveClient(0x4232, 0) # ServiceAgent=B2 # Specify FileAttributes for the new file: btrieveFileAttributes = btrv.BtrieveFileAttributes() rc = btrieveFileAttributes.SetFixedRecordLength(recordLength) # Specify Key 0 as an autoinc: btrieveKeySegment = btrv.BtrieveKeySegment() rc = btrieveKeySegment.SetField(0, 4, btrv.Btrieve.DATA_TYPE_AUTOINCREMENT) btrieveIndexAttributes = btrv.BtrieveIndexAttributes() rc = btrieveIndexAttributes.AddKeySegment(btrieveKeySegment) rc = btrieveIndexAttributes.SetDuplicateMode(False) rc = btrieveIndexAttributes.SetModifiable(True) # Create the file: rc = btrieveClient.FileCreate(btrieveFileAttributes, btrieveIndexAttributes, btrieveFileName, btrv.Btrieve.CREATE_MODE_OVERWRITE) if (rc == btrv.Btrieve.STATUS_CODE_NO_ERROR): print('nFile "' + btrieveFileName + '" created successfully!') else: print('nFile "' + btrieveFileName + '" not created; error: ', rc) # Allocate a file object: btrieveFile = btrv.BtrieveFile() # Open the file: rc = btrieveClient.FileOpen(btrieveFile, btrieveFileName, None, btrv.Btrieve.OPEN_MODE_NORMAL) if (rc == btrv.Btrieve.STATUS_CODE_NO_ERROR): print('File open successful!n') else: print('File open failed - status: ', rc, 'n') # Insert records: iinserting = True while iinserting: new_name = input('Insert name (Q to quit): ' ) if new_name.lower() == 'q': iinserting = False else: record = struct.pack(recordFormat, 0, 0, new_name.ljust(32).encode('UTF-8'), 0, 22, 1, 2018) rc = btrieveFile.RecordCreate(record) if (rc == btrv.Btrieve.STATUS_CODE_NO_ERROR): print(' Insert successful!') else: print(' Insert failed - status: ', rc) # Get Record count: btrieveFileInfo = btrv.BtrieveFileInformation() rc = btrv.BtrieveFile.GetInformation(btrieveFile, btrieveFileInfo) print('nTotal Records inserted =', btrieveFileInfo.GetRecordCount()) # Close the file: rc = btrieveClient.FileClose(btrieveFile) if (rc == btrv.Btrieve.STATUS_CODE_NO_ERROR): print('File closed successful!') else: print('File close failed - status: ', rc)
Comme l'exemple ci-dessus n'effectue aucune lecture de données, j'ai ajouté un peu plus de code avant la fermeture du fichier pour démontrer une analyse du fichier à la recherche d'un nom :
# Recherche de l'enregistrement par nom ireading = True while ireading : find_name = input('nTrouve le nom (Q pour quitter) : ' ) si find_name.lower() == 'q' : ireading = False else : foundOne = False enregistrement = struct.pack(recordFormat, 0, 0, ' '.ljust(32).encode('UTF-8'), 0, 0, 0, 0, 0) readLength = btrieveFile.RecordRetrieveFirst(btrv.Btrieve.INDEX_NONE, enregistrement, 0) while (readLength > 0) : recordUnpacked = struct.unpack(recordFormat, enregistrement) if (recordUnpacked[2] == find_name.ljust(32).encode('UTF-8')) : print('enregistrement correspondant trouvé : ID:', recordUnpacked[0], ' Name:', recordUnpacked[2].decode()) foundOne = True readLength = btrieveFile.RecordRetrieveNextenregistrement, 0) si (foundOne == False) : print(' No enregistrement found matching "'+find_name+'"") status = btrieveFile.GetLastStatusCode() if (status != btrv.Btrieve.STATUS_CODE_END_OF_FILE) : print(' Read error : ', status, btrv.Btrieve.StatusCodeToString(status))
La simplicité de la programmation Python combinée à la nouvelle interface de développement de Btrieve 2 permettra la mise en place rapide de nouvelles applications Zen !
Si vous avez des questions sur Zen ou d'autres produits Actian, n'hésitez pas à les poser dans nos forums communautaires.
S'abonner au blog d'Actian
Abonnez-vous au blogue d'Actian pour recevoir des renseignements sur les données directement à vous.
- Restez informé - Recevez les dernières informations sur l'analyse des données directement dans votre boîte de réception.
- Ne manquez jamais un article - Vous recevrez des mises à jour automatiques par courrier électronique pour vous avertir de la publication de nouveaux articles.
- Tout dépend de vous - Modifiez vos préférences de livraison en fonction de vos besoins.