python not correctly save data if I use pypyodbc - python

I wrote a simple script for parsing csv and insert data into SQL Server.
So, the very strange issue is that some variables are lost if I call them in a if condition.
This is the script:
# DB connection
conn = pypyodbc.connect('DRIVER={SQL Server};SERVER=xxx.xxx.xxx.xxx;DATABASE=SCAN;UID=user;PWD=password')
cursor = conn.cursor()
def main() :
reader = csv.reader(file(filename, "rb"), delimiter=';')
for row in reader :
ip = row[0]
host = row[1]
domain = row[2]
# get Operating System ID
os_id = getOperatingSystem(row[3])
manufacturer = row[4]
model = row[5]
# get computer_manufacturer ID
computer_manufacturer = getManufacturer(manufacturer, computer_model)
arch = getArch(row[6])
values = [ip, host, domain, os_id, manufacturer, arch]
hostIP = getHostIP(ip)
print "hostIP: " +str(hostIP)
if hostIP == 0:
print values
# insert values in DB
cursor.execute(
"""
INSERT INTO dbo.hosts (ip, host, domain, os_id, manufacturer, arch_id)
VALUES (?, ?, ?, ?, ?, ?)
""", values)
cursor.commit()
# return host IP ID
def getHostIP(hostIP) :
cursor.execute("SELECT id FROM mytable WHERE ip = ?", [hostIP])
row = cursor.fetchone()
if row is not None :
return row[0]
return 0
# return ID of Computer Manufacturer
def getComputerManufacturer(manufacturer, computer_model) :
cursor.execute("SELECT id FROM manufacturer WHERE manufacturer = ? AND computer_model = ?", [manufacturer, computer_model])
row = cursor.fetchone()
if row is not None:
return row[0]
else :
return setComputerManufacturer(manufacturer, computer_model)
If I commented cursor_execute and cursor_commit lines the print values correctly shows data, else it shows only the same csv line.
Can you give me a little help?
Thanks

Related

Issue with taking input from the COM port

I am trying to make it so that when a certain number comes through the COM port it updates a value within my sql table as can be seen in the code below
import sqlite3
import serial
def get_attendance_status():
# Connect to the database
conn = sqlite3.connect('attendance.db')
c = conn.cursor()
# Select all rows from the 'students' table
c.execute("SELECT * FROM students")
# Fetch all rows from the cursor
rows = c.fetchall()
# Close the connection to the database
conn.close()
# Return the rows
return rows
def mark_student_present(serial_number):
# Connect to the database
conn = sqlite3.connect('attendance.db')
c = conn.cursor()
# Update the attendance status for the student with the given serial number
c.execute("UPDATE students SET attendance_status = 'present' WHERE serial_number = ?", (serial_number,))
# Commit the changes to the database
conn.commit()
# Close the connection to the database
conn.close()
def create_database_and_table():
# Connect to the database
conn = sqlite3.connect('attendance.db')
c = conn.cursor()
# Create the table if it doesn't already exist
c.execute('''CREATE TABLE IF NOT EXISTS students (
id INTEGER PRIMARY KEY,
serial_number CHAR(10) UNIQUE,
name VARCHAR(255),
attendance_status VARCHAR(255)
)''')
# Reset the attendance status of all students to 'absent'
c.execute("UPDATE students SET attendance_status = 'absent'")
# Add the students to the table if they don't already exist
c.execute("INSERT OR IGNORE INTO students (serial_number, name, attendance_status) VALUES (?, ?, ?)", (1, 'Declan', 'absent'))
c.execute("INSERT OR IGNORE INTO students (serial_number, name, attendance_status) VALUES (?, ?, ?)", (2, 'Milan', 'absent'))
# Commit the changes to the database
conn.commit()
# Close the connection to the database
conn.close()
def main():
# Create the database and table if they don't already exist
create_database_and_table()
# Open the serial port
ser = serial.Serial('COM5', 115200)
# Continuously read serial numbers from the serial port and mark the corresponding students as present
while True:
# Read a line of input from the serial port
serial_number = ser.readline()
# Check if the user entered "exit" on the command line
if serial_number.lower() == 'exit':
break
# Mark the student as present
mark_student_present(serial_number)
# Get the attendance status for all students
rows = get_attendance_status()
# Print the attendance status for each student
for row in rows:
serial_number = row[1]
name = row[2]
attendance_status = row[3]
print(f'{name} ({serial_number}): {attendance_status}')
if __name__ == '__main__':
main()
However when I run the scrip I get this error
TypeError: mark_student_present() missing 1 required positional argument: 'serial_number'
[Done] exited with code=1 in 0.113 seconds
I want it to continuously check the com port to see if the numbers relating to the sql table are recieved. If they are recieved it should then change the attendance_status value.

How to save specific variable in for loop in to the database?

I have a code script that get group id and run some wmi commands for this groups.
I have several wmi commands like get ip, get computer manufacturer, get computer username and so on. I want to save this outputs in database. Like after get ip, get database and write it on ip column. And the same things for other parameters like manufacturer and username.
How can i do it? Im so confused because in my for loop I run all the commands in order.
query = f"select wmic_id from group_wmic where group_id = '{group_id}'"
cursor = connection.cursor(dictionary=True)
cursor.execute(query)
wmic_ids = cursor.fetchall()
for row in wmic_ids:
wmic_id = row["wmic_id"]
query = f"select command_line from wmic_commands where id = '{wmic_id}'"
cursor = connection.cursor(dictionary=True)
cursor.execute(query)
command_line = cursor.fetchall()
for data in command_line:
cmd_line = data['command_line']
output = wmi.query(cmd_line)
result = json.dumps(output)
mySql_insert_query = """INSERT INTO wmi_inventory (wmi_data, date)
VALUES (%s, %s) """
now = datetime.now()
dt_string = now.strftime("%Y-%m-%d-%H:%M:%S")
record = (result, dt_string)
cursor.execute(mySql_insert_query, record)
connection.commit()
For being more clear,
I have commands like:
SELECT UserName FROM Win32_ComputerSystem
which gives me the username of computer. or SELECT Manufacturer, Model FROM Win32_ComputerSystem it gives me the manufacturer.
In this part of my code
query = f"select command_line from wmic_commands where id = '{wmic_id}'"
cursor = connection.cursor(dictionary=True)
cursor.execute(query)
command_line = cursor.fetchall()
**for data in command_line:
cmd_line = data['command_line']
output = wmic.query(cmd_line)**
result = json.dumps(output)
mySql_insert_query = """INSERT INTO wmi_inventory (wmi_data, date)
VALUES (%s, %s) """
now = datetime.now()
dt_string = now.strftime("%Y-%m-%d-%H:%M:%S")
record = (result, dt_string)
cursor.execute(mySql_insert_query, record)
connection.commit()
I execute all these queries in my for loop. And save the output as a json data in my database. But i want to save outputs in to the database like when i execute the username commands, save it in to username column.

Incorrect Number of Bindings Error with SQLite

A little background I am doing this in python 2.7 for the reason of Alexa Rank through SeoLib but am completely open to updating if that would help this issue or possibly solve future issues.
Now this program sorts through sites that I have in a predetermined csv that looks like the following:
site
00rbt.com
I am specifically getting the following error:
File "igorPanda.py", line 84, in <module>
update_site(site,cur_ip,cur_rank,cur_hash)
File "igorPanda.py", line 30, in update_site
(site))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied.
Where this error is occuring is:
def update_site(site,cur_ip,cur_rank,cur_hash):
conn = sqlite3.connect('/root/Database/Sites.db')
cursor = conn.cursor()
with conn:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)",
(site))
record = cursor.fetchone()
if record[0] == 1:
cursor.execute("UPDATE sites SET cur_ip = ?, cur_rank = ?, cur_hash = ? WHERE site = ?",
(cur_ip,cur_rank,cur_hash,site))
else:
cursor.execute("INSERT into sites values (?,?,?,?,?,?,?,?)",
(site,cur_ip,None,cur_rank,None,None,cur_hash,None))
My entire code except imports is:
#Updates the DB
def update_site(site,cur_ip,cur_rank,cur_hash):
conn = sqlite3.connect('/root/Database/Sites.db')
cursor = conn.cursor()
with conn:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)",
(site))
record = cursor.fetchone()
if record[0] == 1:
cursor.execute("UPDATE sites SET cur_ip = ?, cur_rank = ?, cur_hash = ? WHERE site = ?",
(cur_ip,cur_rank,cur_hash,site))
else:
cursor.execute("INSERT into sites values (?,?,?,?,?,?,?,?)",
(site,cur_ip,None,cur_rank,None,None,cur_hash,None))
#Moves CSV for Historical Savings
bashmove = "mv top.csv /root/Desktop/scripts/results-igor/top-$(date +%m-%d-%Y).csv"
#Sets file with all sites to variable
filename='/root/Desktop/scripts/sorted.csv'
#Creates hash algorithm for later use
hasher = hashlib.sha256()
sess = requests.Session()
x = datetime.datetime.now()
date = x.strftime('%Y-%m-%d')
regex = r"^(?:https?:)?(?:\/\/)?(?:[^#\n]+#)?(?!www\.)?([^:\/\n]+)\w*\.\b(com|org|co|be|de|br|(\w+\b))" #regex to get stripepd website no https://www. or anything afte$
df = pd.DataFrame()
df = df.append(pd.read_csv(filename), ignore_index=True)
ip = "NOT FOUND"
for i in df.index:
#print(i)
site = df['site'][i]
try :
ip = socket.gethostbyname(site)
page = requests.get('http://' + df['site'][i], timeout=5)
hasher.update((page.text).encode('utf-8'))
except: #ignore errors if the site is bad
pass
try :
alexa_rank = seo.get_alexa('http://{}'.format(site)) #seolib gets the alexa ranking
#alexa_rank = None
except:
pass
site = site
cur_ip = ip
cur_rank = alexa_rank
cur_hash = hasher.hexdigest()
update_site(site,cur_ip,cur_rank,cur_hash)
rd = call(["/root/Desktop/scripts/./rDNSlookup.sh", site, ip]) #call bash script to get reverse DNS of ip
wi = call(["/root/Desktop/scripts/./whois.sh", site]) #call bash script to print host info
with open('/root/Desktop/scripts/IGOR_His/'+ date + 'sites.csv', 'a') as f:
print >> f, 'site: ',site,', ip: ',ip,', rank: ',alexa_rank, ', hash', cur_hash
shutil.copy("/root/Database/Sites.db", "/var/www/html/sites/Sites.db")
The table has the following columns:
site,cur_ip,prev_ip,cur_rank,prev_rank,play,cur_hash,prev_hash
TL;DR: use (site,)
In detail:
cursor.execute expects the second paramter to be an iterable.
When your code says:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))
Then (site) is not a tuple - you probably meant to convert it to a tuple by wrapping it in ().
So what you meant/want is:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site,))
Notice the extra ,!
To avoid this tuple confusion, you can also use a list:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", [site])
The issue in even more detail:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))
is the same as:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", site)
is the same (in your case) as:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", "00rbt.com")
The string 00rbt.com is used as iterable, and since it has 9 characters, you get the error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied.
You get this error, because here:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))
you should pass, as the 2nd argumnet of execute() a tuple and not just a string.
This is easily fixed by adding a comma like this:
cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site,))
But, if your version of SQLite is 3.24.0+, you should consider taking a different approach by choosing UPSERT as the method to do what you want.
You want to insert a new row if the site value does not exist in the table or update the existing row if it does exist.
So, assuming there is already a unique constraint for the column site, you can do it more efficiently with:
sql = """
INSERT into sites values (?,?,?,?,?,?,?,?)
ON CONFLICT(site) DO UPDATE SET
cur_ip = EXCLUDED.cur_ip, cur_rank = EXCLUDED.cur_rank, cur_hash = EXCLUDED.cur_hash
"""
cursor.execute(sql, (site,cur_ip,None,cur_rank,None,None,cur_hash,None))

python script is not saving into database

I am currently learning how to modify data with python using visual studios and sqlite. My assignment is to count how many times emails are found in a file, organize them in a way that each email is then counted. Then I must input these into SQLite as a table named Counts with two rows (org,count). I have wrote a code that runs the program and outputs it onto the visual studios output screen but not the database.
this is my program:
import sqlite3
conn = sqlite3.connect('database3.db')
cur = conn.cursor()
cur.execute('DROP TABLE IF EXISTS Counts')
cur.execute('''CREATE TABLE Counts (email TEXT, count INTEGER)''')
#cur.execute("INSERT INTO Counts Values('mlucygray#gmail.com',1)")
# Save (commit) the changes
conn.commit()
fname = input('Enter file name: ')
if (len(fname) < 1): fname = 'mbox-short.txt'
fh = open(fname)
for line in fh:
if not line.startswith('From: '): continue
pieces = line.split()
email = pieces[1]
cur.execute('SELECT count FROM Counts WHERE email = ? ', (email,))
row = cur.fetchone()
if row is None:
cur.execute('''INSERT INTO Counts (email, count) VALUES (?, 1)''', (email,))
else:
cur.execute('UPDATE Counts SET count = count + 1 WHERE email = ?',(email,))
cur.execute('SELECT * FROM Counts')
# https://www.sqlite.org/lang_select.html
sqlstr = 'SELECT email, count FROM Counts ORDER BY count DESC LIMIT 10'
conn.commit()
for row in cur.execute(sqlstr):
print(str(row[0]), row[1])
conn.commit()
cur.close()
click here for the link to the output of the above code
Thank you for any suggestions
You need to commit changes with insert/update and DONT need to commit after executing select statements.
for line in fh:
if not line.lower().startswith('from: '): continue
pieces = line.split()
email = pieces[1]
cur.execute('SELECT count FROM Counts WHERE email = ?', (email,))
row = cur.fetchone()
if row is None:
cur.execute('''INSERT INTO Counts (email, count) VALUES (?, 1)''', (email,))
else:
cur.execute('UPDATE Counts SET count = count + 1 WHERE email = ?',(email,))
conn.commit()
sqlstr = 'SELECT email, count FROM Counts ORDER BY count DESC LIMIT 10'
for row in cur.execute(sqlstr):
print(str(row[0]), row[1])
cur.close()

Loop Through an Table in SQL and Update a row every time

and having lots of trouble trying to figure out how I can update several rows in a SQLite data base.
Efectively I am getting an location on a Database I gathered, and running through Google maps to get the Latitude and Longitude. In general its working, but the loop fails!
It does it once, gets the first line that meet criteria and finish, and I can´t figure it out why it´s not keep going!! Can anyone help? The script below:
# coding=utf-8
import urllib
import sqlite3
import json
conn = sqlite3.connect('ArchDailyProjects.sqlite')
cur = conn.cursor()
#Google Prep
ServiceUrl="https://maps.googleapis.com/maps/api/geocode/json?"
FimDoURL="&key=????????????????????????????????" #I have the key right, this part works fine
#cur.execute('SELECT * FROM Lugares' )
#print type(cur)
#print cur
#row=cur.fetchone()
for row in cur.execute('SELECT * FROM LugareS' ):
print 'Entramos no While'
Loc_id = str(row[0])
Loc_Name = str(row[1])
Loc_Lat = row[2]
print Loc_Name
if Loc_Lat is None:
print Loc_Name
print Loc_Lat
print "Buscando "+Loc_Name+" no Google Maps"
try:
Url = ServiceUrl + urllib.urlencode({"sensor": "false", "address": Loc_Name}) + FimDoURL
Uh = urllib.urlopen(Url)
Dados = Uh.read()
try: js = json.loads(str(Dados))
except: js = None
except: continue
if "status" not in js or js["status"] != "OK":
print "===== Beeehhhh!!! Não conseguimos encontrar essa cidade===="
print Dados
continue
else:
Loc_FormatedAdress = js["results"][0]["formatted_address"]
Loc_Lat = js["results"][0]["geometry"]["location"]["lat"]
Loc_Lon = js["results"][0]["geometry"]["location"]["lng"]
print Dados
print 'Endereço Google: ', Loc_FormatedAdress
print 'Latitude: ', Loc_Lat
print 'Longitude: ', Loc_Lon
cur.execute('''UPDATE Lugares SET Latitude= ?, Longitude=?, GoogleLoc=? WHERE id= ?
''', (Loc_Lat, Loc_Lon, Loc_FormatedAdress, Loc_id))
#row=cur.fetchone()
else: #row=cur.fetchone()
continue
conn.commit()
Thank you guys!
If the file is large, you may not want to load the entire database into memory with "fetchall" but read only one row at a time, and update entries on the go. You can do this by creating two cursors.
import sqlite3 as sq3
conn = sq3.connect(db_name)
cur = conn.cursor()
cur2 = conn.cursor()
for row in cur.execute('SELECT * FROM Table' ):
cur2.execute('''UPDATE Table SET variable = ? WHERE id= ?''', (variable, id))
works fine.
for row in cur.execute('SELECT * FROM LugareS' ):
...
cur.execute('''UPDATE Lugares SET Latitude= ?, Longitude=?, GoogleLoc=? WHERE id= ?
You are executing a different query on the same cursor object; the UPDATE does not have any result rows.
Simply read all the data before looping over it:
cur.execute('SELECT id, Name FROM Lugares WHERE Latitude IS NULL')
empty_rows = cur.fetchall()
for row in empty_rows:
...

Categories