मैं पायथन का उपयोग करके जेडीबीसी (या ओडीबीसी) के साथ आईआरआईएस डेटाबेस तक पहुंच रहा हूं। मैं डेटा में हेरफेर करने और उससे चार्ट बनाने के लिए डेटा को pandas डेटाफ़्रेम में लाना चाहता हूं। जेडीबीसी का उपयोग करते समय मुझे स्ट्रिंग हैंडलिंग में समस्या का सामना करना पड़ा। यदि किसी और को भी यही समस्या है तो यह पोस्ट मदद के लिए है। या, यदि इसे हल करने का कोई आसान तरीका है, तो मुझे टिप्पणियों में बताएं!
मैं ओएसएक्स का उपयोग कर रहा हूं, इसलिए मैं अनिश्चित हूं कि मेरी समस्या कितनी अनोखी है। मैं ज्यूपिटर नोटबुक का उपयोग कर रहा हूं, हालांकि यदि आप किसी अन्य पायथन प्रोग्राम या फ्रेमवर्क का उपयोग करते हैं तो कोड आम तौर पर वही होगा।
जब मैं डेटाबेस से डेटा लाता हूं तो कॉलम विवरण और कोई भी स्ट्रिंग डेटा डेटा प्रकार java.lang.String के रूप में लौटाया जाता है। यदि आप स्ट्रिंग डेटा डेटा प्रिंट करते हैं तो यह अपेक्षित "दर्दनाक" के बजाय इस तरह दिखेगा: "(p,a,i,n,i,n,t,h,e,r,e,a,r)"।
ऐसा शायद इसलिए है क्योंकि JDBC का उपयोग करके लाए जाने पर डेटा प्रकार java.lang.String के कैरेक्टर स्ट्रिंग एक पुनरावर्तनीय या सरणी के रूप में आ रहे हैं। ऐसा तब हो सकता है जब आप जिस Python-Java ब्रिज का उपयोग कर रहे हैं (उदाहरण के लिए, JayDeBeApi, JDBC) एक ही चरण में java.lang.String को Python str में स्वचालित रूप से परिवर्तित नहीं कर रहा है।
पायथन की स्ट्रिंग स्ट्रिंग प्रस्तुति, इसके विपरीत, पूरी स्ट्रिंग को एक इकाई के रूप में रखती है। जब पायथन एक सामान्य str पुनर्प्राप्त करता है (उदाहरण के लिए ODBC के माध्यम से), तो यह अलग-अलग वर्णों में विभाजित नहीं होता है।
इस समस्या को ठीक करने के लिए, आपको यह सुनिश्चित करना होगा कि java.lang.String सही ढंग से पायथन के str प्रकार में परिवर्तित हो गया है। प्राप्त डेटा को संसाधित करते समय आप इस रूपांतरण को स्पष्ट रूप से संभाल सकते हैं ताकि इसे पुनरावर्तनीय या वर्णों की सूची के रूप में व्याख्या न किया जाए।
इस स्ट्रिंग हेरफेर को करने के कई तरीके हैं; यह जो मैंने किया है।
import pandas as pd import pyodbc import jaydebeapi import jpype def my_function(jdbc_used) # Some other code to create the connection goes here cursor.execute(query_string) if jdbc_used: # Fetch the results, convert java.lang.String in the data to Python str # (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,r,e,a,r)" Convert to str type "painintherear" results = [] for row in cursor.fetchall(): converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row] results.append(converted_row) # Get the column names and ensure they are Python strings column_names = [str(col[0]) for col in cursor.description] # Create the dataframe df = pd.DataFrame.from_records(results, columns=column_names) # Check the results print(df.head().to_string()) else: # I was also testing ODBC # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall() results = cursor.fetchall() # Get the column names column_names = [column[0] for column in cursor.description] # Create the dataframe df = pd.DataFrame.from_records(results, columns=column_names) # Do stuff with your dataframe
ODBC कनेक्शन का उपयोग करते समय, स्ट्रिंग वापस नहीं आती हैं या NA होती हैं।
यदि आप किसी ऐसे डेटाबेस से कनेक्ट कर रहे हैं जिसमें यूनिकोड डेटा है (उदाहरण के लिए, विभिन्न भाषाओं में नाम) या यदि आपके एप्लिकेशन को गैर-एएससीआईआई वर्णों को संग्रहीत या पुनर्प्राप्त करने की आवश्यकता है, तो आपको यह सुनिश्चित करना होगा कि डेटा के बीच पारित होने पर डेटा सही ढंग से एन्कोड किया गया हो डेटाबेस और आपका पायथन एप्लिकेशन।
यह कोड सुनिश्चित करता है कि डेटाबेस में डेटा भेजते और पुनर्प्राप्त करते समय स्ट्रिंग डेटा को UTF-8 का उपयोग करके एन्कोड और डिकोड किया जाता है। गैर-ASCII वर्णों से निपटने या यूनिकोड डेटा के साथ संगतता सुनिश्चित करते समय यह विशेष रूप से महत्वपूर्ण है।
def create_connection(connection_string, password): connection = None try: # print(f"Connecting to {connection_string}") connection = pyodbc.connect(connection_string ";PWD=" password) # Ensure strings are read correctly connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8") connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8") connection.setencoding(encoding="utf8") except pyodbc.Error as e: print(f"The error '{e}' occurred") return connection
connection.setdecoding(pyodbc.SQL_CHAR, encoding='utf8'')
pyodbc को बताता है कि SQL_CHAR प्रकार (आमतौर पर, निश्चित-लंबाई वर्ण फ़ील्ड) लाते समय डेटाबेस से कैरेक्टर डेटा को कैसे डीकोड किया जाए।
connection.setdecoding(pyodbc.SQL_WCHAR, encoding='utf8'')
SQL_WCHAR, विस्तृत-वर्ण प्रकार (यानी, यूनिकोड स्ट्रिंग्स, जैसे SQL सर्वर में NVARCHAR या NCHAR) के लिए डिकोडिंग सेट करता है।
connection.setencoding(encoding='utf8''
यह सुनिश्चित करता है कि पायथन से डेटाबेस में भेजे गए किसी भी स्ट्रिंग या कैरेक्टर डेटा को UTF-8 का उपयोग करके एन्कोड किया जाएगा,
जिसका अर्थ है कि डेटाबेस के साथ संचार करते समय पायथन अपने आंतरिक str प्रकार (जो यूनिकोड है) को UTF-8 बाइट्स में अनुवादित करेगा।
JAVA स्थापित करें - dmg का उपयोग करें
https://www.oracle.com/middleeast/java/technologies/downloads/#jdk23-mac
डिफ़ॉल्ट संस्करण सेट करने के लिए शेल को अपडेट करें
$ /usr/libexec/java_home -V Matching Java Virtual Machines (2): 23 (arm64) "Oracle Corporation" - "Java SE 23" /Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home 1.8.421.09 (arm64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home /Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home $ echo $SHELL /opt/homebrew/bin/bash $ vi ~/.bash_profile
अपने पथ में JAVA_HOME जोड़ें
export JAVA_HOME=$(/usr/libexec/java_home -v 23) export PATH=$JAVA_HOME/bin:$PATH
जेडीबीसी ड्राइवर प्राप्त करें
https://intersystems-community.github.io/iris-driver-distribution/
जार फ़ाइल को कहीं रखें... मैंने इसे $HOME में रखा है
$ ls $HOME/*.jar /Users/myname/intersystems-jdbc-3.8.4.jar
यह मान लिया गया है कि आपने ओडीबीसी स्थापित कर लिया है (किसी अन्य दिन के लिए एक उदाहरण, कुत्ते ने मेरे नोट्स खा लिए...)।
नोट: यह मेरे वास्तविक कोड का हैक है। चर नामों पर ध्यान दें।
import os import datetime from datetime import date, time, datetime, timedelta import pandas as pd import pyodbc import jaydebeapi import jpype def jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password): # Path to JDBC driver jdbc_driver_path = '/Users/yourname/intersystems-jdbc-3.8.4.jar' # Ensure JAVA_HOME is set os.environ['JAVA_HOME']='/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home' os.environ['CLASSPATH'] = jdbc_driver_path # Start the JVM (if not already running) if not jpype.isJVMStarted(): jpype.startJVM(jpype.getDefaultJVMPath(), classpath=[jdbc_driver_path]) # Connect to the database connection = None try: connection = jaydebeapi.connect("com.intersystems.jdbc.IRISDriver", jdbc_url, [jdbc_username, jdbc_password], jdbc_driver_path) print("Connection successful") except Exception as e: print(f"An error occurred: {e}") return connection def odbc_create_connection(connection_string): connection = None try: # print(f"Connecting to {connection_string}") connection = pyodbc.connect(connection_string) # Ensure strings are read correctly connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8") connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8") connection.setencoding(encoding="utf8") except pyodbc.Error as e: print(f"The error '{e}' occurred") return connection # Parameters odbc_driver = "InterSystems ODBC" odbc_host = "your_host" odbc_port = "51773" odbc_namespace = "your_namespace" odbc_username = "username" odbc_password = "password" jdbc_host = "your_host" jdbc_port = "51773" jdbc_namespace = "your_namespace" jdbc_username = "username" jdbc_password = "password" # Create connection and create charts jdbc_used = True if jdbc_used: print("Using JDBC") jdbc_url = f"jdbc:IRIS://{jdbc_host}:{jdbc_port}/{jdbc_namespace}?useUnicode=true&characterEncoding=UTF-8" connection = jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password) else: print("Using ODBC") connection_string = f"Driver={odbc_driver};Host={odbc_host};Port={odbc_port};Database={odbc_namespace};UID={odbc_username};PWD={odbc_password}" connection = odbc_create_connection(connection_string) if connection is None: print("Unable to connect to IRIS") exit() cursor = connection.cursor() site = "SAMPLE" table_name = "your.TableNAME" desired_columns = [ "RunDate", "ActiveUsersCount", "EpisodeCountEmergency", "EpisodeCountInpatient", "EpisodeCountOutpatient", "EpisodeCountTotal", "AppointmentCount", "PrintCountTotal", "site", ] # Construct the column selection part of the query column_selection = ", ".join(desired_columns) query_string = f"SELECT {column_selection} FROM {table_name} WHERE Site = '{site}'" print(query_string) cursor.execute(query_string) if jdbc_used: # Fetch the results results = [] for row in cursor.fetchall(): converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row] results.append(converted_row) # Get the column names and ensure they are Python strings (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,a,r,s,e)" column_names = [str(col[0]) for col in cursor.description] # Create the dataframe df = pd.DataFrame.from_records(results, columns=column_names) print(df.head().to_string()) else: # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall() results = cursor.fetchall() # Get the column names column_names = [column[0] for column in cursor.description] # Create the dataframe df = pd.DataFrame.from_records(results, columns=column_names) print(df.head().to_string()) # # Build charts for a site # cf.build_7_day_rolling_average_chart(site, cursor, jdbc_used) cursor.close() connection.close() # Shutdown the JVM (if you started it) # jpype.shutdownJVM()
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3