Python und Btrieve 2 unter Windows: Zugriff auf Zen-Daten mit NoSQL
Actian Germany GmbH
2. Februar 2018

In meinem letzten Blog ("Programmierung auf die einfache Art: Zugriff auf eine PSQL-Zen-Datenbank mit Python und ODBC") habe ich gezeigt, wie man mit Python und ODBC einfach auf eine ActianZen-Datenbank zugreifen kann. Mein nächstes Projekt bestand darin, die neue Funktion von Btrieve 2 mit Python zu nutzen, um direkt auf die Datendateien zuzugreifen, ohne SQL zu verwenden.
Langjährige Btrieve/PSQL/Zen-Kunden sind mit der alten Btrieve-Funktion vertraut, einer klassischen 3GL-Programmierschnittstelle, die sich seit über 30 Jahren nicht wirklich verändert hat. Sie bietet direkten Zugriff auf die Engine, so dass Sie Datendateien mit Optionen wie Create, Open, Insert, Update, Delete, GetFirst, GetNext, GetEqual usw. manipulieren können. Mit Actian Zen v13 gibt es nun Btrieve 2, das eine vereinfachte, intuitivere objektorientierte Schnittstelle bietet, die alle Btrieve-Aufrufe an die Datenbank-Engine abdeckt. Diese Schnittstelle ist für C/C++-Entwickler gedacht, aber wir stellen auch SWIG-Dateien (Simplified Wrapper & Interface Generator) zur Verfügung, so dass die Schnittstelle auch von Python, Perl- und PHP-Entwicklern genutzt werden kann.
Die Einrichtung von Btrieve 2 mit Python erfordert ein paar Schritte:
- Bereiten Sie Ihre Windows-Umgebung vor:
- Installieren Sie die Actian Zen v13 Datenbank-Engine
- Python für Windows installieren - ich habe v3.6 64-bit von python.org verwendet
- Swig für Windows herunterladen und entpacken - ich habe Swigwin-3.0.12 von swig.org verwendet
- Herunterladen und Entpacken des Btrieve 2 SDK
- Visual Studio 2015 oder höher ist ebenfalls erforderlich; Sie können eine Community-Version von Microsoft installieren, wenn Sie nicht bereits eine von hier haben.
- Erstellen Sie einen MyPrograms-Ordner für Ihren Python , und kopieren Sie die folgenden Dateien aus dem Btrieve 2 SDK hinein:
- btrieveCpp.lib & btrieveC.lib von win64
- btrieveC.h & btrieveCpp.h von include
- btrievePython.swig & btrieveSwig.swig von swig
- Öffnen Sie eine Eingabeaufforderung, wechseln Sie in den Ordner MyPrograms und geben Sie den folgenden Befehl ein:
<swigwin_location>swig -c++ -D_WIN64 -python btrievePython.swig
Dies erzeugt die folgenden Dateien: btrievePython.py & btrievePython_wrap.cxx - Erstellen Sie in MyPrograms eine Textdatei mit dem Namen setup.py, die Folgendes enthält:
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"], )
- Führen Sie in einer Eingabeaufforderung im Ordner MyPrograms diesen Befehl aus, um das Modul btrievePython zu erstellen:
python setup.py build_ext --plat-name="win-amd64"
Dies erzeugt die kompilierte Python buildlib.win-amd64-3.6_btrievePython.cp36-win_amd64.pyd - Benennen Sie die .pyd-Datei in _btrievePython.pyd um und kopieren Sie sie in den Ordner MyPrograms oder den Ordner DLLs unter Ihrer Python .
Sobald diese Schritte abgeschlossen sind, sollten Sie in der Lage sein, "btrievePython" in einer Python oder einem Programm zu importieren.
Sobald die btrievePython-Importbibliothek eingerichtet ist, sind Sie bereit, Btrieve 2-Anwendungen in Python zu schreiben! Hier ist ein Beispiel, das die gleichen Datenbankoperationen ausführt wie die ODBC-Version aus meinem vorherigen Blog - die gleiche Datei erstellen, Datensätze einfügen und die Gesamtzahl der eingefügten Datensätze abrufen. Dieser Code ist etwa doppelt so lang wie die ODBC-Version, aber er greift direkt auf die Datei zu, ohne die SQL-Schicht zu durchlaufen. (Hinweis: Es wurde nur eine minimale Fehlerprüfung eingebaut):
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)
Da im obigen Beispiel keine Daten gelesen werden, habe ich vor dem Schließen der Datei etwas mehr Code hinzugefügt, um einen Dateiscan zu demonstrieren, der nach einem Namen sucht:
# Aufzeichnung nach Name nachschlagen ireading = True while ireading: find_name = input('nNamen finden (Q zum Beenden): ' ) if find_name.lower() == 'q': ireading = False sonst: foundOne = False Aufzeichnung = struct.pack(recordFormat, 0, 0, ' '.ljust(32).encode('UTF-8'), 0, 0, 0, 0) readLength = btrieveFile.RecordRetrieveFirst(btrv.Btrieve.INDEX_NONE, Aufzeichnung, 0) while (readLength > 0): recordUnpacked = struct.unpack(recordFormat, Aufzeichnung) if (recordUnpacked[2] == find_name.ljust(32).encode('UTF-8')): print(' Passende Aufzeichnung gefunden: ID:', recordUnpacked[0], ' Name:', recordUnpacked[2].decode()) foundOne = True readLength = btrieveFile.RecordRetrieveNextAufzeichnung, 0) if (foundOne == False): print(' Keine Aufzeichnung mit "'+find_name+'"' gefunden) status = btrieveFile.GetLastStatusCode() if (status != btrv.Btrieve.STATUS_CODE_END_OF_FILE): print(' Lesefehler: ', status, btrv.Btrieve.StatusCodeToString(status))
Die Einfachheit der Python in Kombination mit der neuen Btrieve 2-Entwicklungsschnittstelle ermöglicht eine schnelle Umsetzung neuer Zen-Anwendungen!
Wenn Sie Fragen zu Zen oder anderen ActianProdukten haben, können Sie diese gerne in unseren Community-Foren stellen.
Abonnieren Sie den Actian Blog
Abonnieren Sie den Blog von Actian, um direkt Dateneinblicke zu erhalten.
- Bleiben Sie auf dem Laufenden - Holen Sie sich die neuesten Informationen zu Data Analytics direkt in Ihren Posteingang.
- Verpassen Sie keinen Beitrag: Sie erhalten automatische E-Mail-Updates, die Sie informieren, wenn neue Beiträge veröffentlicht werden.
- Ganz wie sie wollen: Ändern Sie Ihre Lieferpräferenzen nach Ihren Bedürfnissen.