I am trying to write data to a SQL Server 2016 Express database from an Ubuntu 16.04 virtual machine using python. The connection is to be set up via FreeTDS, UnixODBC, pyodbc.
The program gets a string of sensor data over a TCP socket, formats it and writes it to a (new or existing) table. This have to happen every x seconds. Therefor I used this answer.
The code evinces a strange behavior and I tried and searched for hours. It sometimes work and sometimes not. I think the problem is to do with connection = pyodbc.connect(conn_str)
, because often the code is successfully executed once and then gets stuck at this line. After some minutes an Error appears:
connection = pyodbc.connect(conn_str)
Error: ('08S01', '[08S01] [unixODBC][FreeTDS][SQL Server]Unable to connect: Adaptive Server is unavailable or does not exist (20009) (SQLDriverConnect)')
Maybe the problem correlates with an open connection but it should be closed at the end of the script. Do you have a solution? How can I catch such errors with a try/except funktion? Please ask if I should provide more information.
Thank you in advance for your help!
This is the code:
import sys
import pyodbc
import socket
import re
from threading import Timer
import time
# Timer (see link above)
class InfiniteTimer():
def pi_to_sql():
dsn = "sqlserverdatasource"
user = "User"
password = "Password"
database = "MSSQL_DB"
conn_str = "DSN=%s;UID=%s;PWD=%s;DATABASE=%s;" % (dsn, user, password, database)
connection = pyodbc.connect(conn_str)
cursor = connection.cursor()
# Create TCP/IP socket (client)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Create connection with socket server (insert IP of server)
server_address = ('XXX.XXX.XXX.XXX', 10000)
sock.connect(server_address)
# Sending order to server
to_send = "send data"
sock.sendall(to_send)
# Receiving data (string, e.g. "DS18B20;28FF97FF841605C0;32.4375")
data = sock.recv(1024)
# Filter data using regex
data_list = re.findall(r"(?P<name>\w{6,});(?P<address>[0-9A-F]{16,});(?P<value>-?\d+\.?\d+)",data,re.M)
# Closing socket
sock.close()
sensor_cnt = len(data_list)
i = 0
# Write sensor data to new or existing table using a loop
while i<=(sensor_cnt-1):
s_address = data_list[i][1]
s_value = data_list[i][2]
act_datetime = time.strftime("%Y%m%d %H:%M:%S")
table_name = "sensor_" + s_address
sql_command = """IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = '{0:s}'))
BEGIN
CREATE TABLE dbo.{0:s}
(
Timestamp DATETIME2(0),
S_Value FLOAT
)
END
INSERT INTO dbo.{0:s} VALUES
(
'{1:s}','{2:s}'
)""".format(table_name,act_datetime,s_value)
try:
cursor.execute(sql_command)
connection.commit()
except pyodbc.ProgrammingError:
print("error")
connection.close()
i = i+1
cursor.close()
connection.close()
print("done")
# Calling timer class to execute code every 5s
t = InfiniteTimer(5, pi_to_sql)
t.start()
tsql -C (I used the latest stable .tar.gz from FreeTDS)
Compile-time settings (established with the "configure" script)
Version: freetds v1.00.27
freetds.conf directory: /usr/local/etc
MS db-lib source compatibility: no
Sybase binary compatibility: no
Thread safety: yes
iconv library: yes
TDS version: 7.4
iODBC: no
unixodbc: yes
SSPI "trusted" logins: no
Kerberos: no
OpenSSL: no
GnuTLS: no
MARS: no
/etc/odbc.ini
[sqlserverdatasource]
driver = /usr/local/lib/libtdsodbc.so
server = XXX.XXX.XXX.XXX
port = 61521
database = MSSQL_DB
tds_version = 7.4
isql -v sqlserverdatasource User Password
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>