Handling 'UnboundLocalError' caused by invalid input - python

I'm writing a simple application that allows a user to create a playlist in a SQLite database using a text file input. My code works, but when it encounters a line in the .txt file that is not in the database I get: 'UnboundLocalError: cannot access local variable 'trackId' where it is not associated with a value'. This is logical, because there is no value in the case that one of the tracks (lines) is not in the database.
This error happens in the function 'selection_menu'.
I tried an if-else statement:
def selection_menu(track_selection):
if track_selection is None:
print("Error: track_selection is None")
else:
for position, song in enumerate(track_selection):
print(str(position + 1), song[1], song[2], sep='\t')
choice = int(input('Choose from the following options: '))
selected_track = track_selection[choice - 1]
print('You chose:', selected_track[1], selected_track[2], sep='\t')
trackId = selected_track[0]
playlistId = get_playlistId(playlist)
add_track_to_playlist(trackId, playlistId)
return trackId, playlistId
This does give the print statement 'Error: track_selection is None', but this doesn't solve the error.
I guess I need a try-except block, but I have failed to integrate this properly. How can I make this work?
Below the full code:
import sqlite3
from pathlib import Path
database_file = "C:\\Users\marlo\Downloads\chinook_LOI.db"
# Check if file exixts
def existing_file():
music_file = Path(input("Give the name of the file: "))
while not music_file.exists():
print("--- File not found ---")
music_file = Path(input("Give the name of the file: "))
return music_file
# check if the playlist exists
def existing_playlist():
music_database = sqlite3.connect(database_file)
cursor = music_database.cursor()
playlist = input("Give the name of the playlist: ")
check_playlist = cursor.execute(f"""SELECT Name
FROM playlists
WHERE Name = '{playlist.title()}'""")
while check_playlist.fetchone() is not None:
print("--- This playlist already exists ---")
playlist = input("Give the name of the playlist: ")
check_playlist = cursor.execute(f"""SELECT Name
FROM playlists
WHERE Name = '{playlist.title()}'""")
return playlist
# add playlist to SQL database
def add_playlist(name_playlist):
music_database = sqlite3.connect(database_file)
cursor = music_database.cursor()
cursor.execute("INSERT INTO playlists (Name) VALUES (?)", [name_playlist])
music_database.commit()
# read the file to find the tracks
def read_file(filename):
music_database = sqlite3.connect(database_file)
cursor = music_database.cursor()
with open(filename) as f:
for line in f:
line = line.strip()
if line:
cursor.execute(f"""SELECT DISTINCT t.TrackId, t.Name, art.Name
FROM tracks t
JOIN albums alb ON t.AlbumId = alb.AlbumId
JOIN artists art ON alb.ArtistId = art.ArtistId
WHERE t.Name LIKE '{line}%'""")
tracks_available = cursor.fetchall()
if len(tracks_available) == 1:
selected_track = tracks_available[0]
trackId = selected_track[0]
playlistId = get_playlistId(playlist)
add_track_to_playlist(trackId, playlistId)
print("Track added:", *selected_track[1:3], sep='\t')
elif tracks_available:
selection_menu(tracks_available)
else:
print(f"Invalid input: {line}")
print("--- Playlist is ready ---")
music_database.close()
# let the user choose the right track if there's multiple opions,
# if there's only one option: continue,
# if there's no option: give error
def selection_menu(track_selection):
if track_selection is None:
print("Error: track_selection is None")
else:
for position, song in enumerate(track_selection):
print(str(position + 1), song[1], song[2], sep='\t')
choice = int(input('Choose from the following options: '))
selected_track = track_selection[choice - 1]
print('You chose:', selected_track[1], selected_track[2], sep='\t')
trackId = selected_track[0]
playlistId = get_playlistId(playlist)
add_track_to_playlist(trackId, playlistId)
return trackId, playlistId
# fetch the right playlistId from the database
def get_playlistId(playlist_name):
music_database = sqlite3.connect(database_file)
cursor = music_database.cursor()
cursor.execute(f"SELECT PlaylistId FROM playlists WHERE Name = '{playlist_name}'")
playlistId = cursor.fetchone()[0]
return playlistId
# add track to playlist
def add_track_to_playlist(trackId, playlistId):
music_database = sqlite3.connect(database_file)
cursor = music_database.cursor()
try:
cursor.execute(f"""INSERT INTO playlist_track (TrackId, PlaylistId) VALUES (?, ?)", '{trackId, playlistId}'""")
except sqlite3.IntegrityError as e:
print("Could not add track to playlist: track already exists in playlist")
music_database.commit()
music_file = existing_file()
playlist = existing_playlist()
add_playlist(playlist)
tracks_available = read_file(filename=music_file)
selection_menu(track_selection=tracks_available)
get_playlistId(playlist)
add_track_to_playlist()
music_database.close()

Related

Try except works when file is run from IDE but when compiled into exe with pyinstaller it doesnt work

I created a python tool with Tkinter GUI. These are the pieces of the script. The problem is with the try-except in these lines of code.
try:
pldf_csv[data['sls_data']['add_columns']].write_csv(endpath,sep='\t')
except:
write_eror_status = True
print("CANNOT WRITE FILE")
If I run the python file via VSCode the try-except works like this
But then if I compile the script with pyinstaller to exe, those line doesn't execute at all
Full code
class IngestGenerator:
def __init__(self, fn,fd,n3pl):
self.filename = fn
self.filedir = fd
self.name3pl = n3pl
def generate_result_csv(self):
"""To extend 3PL please refer to comment with <(extend this)> note
Don't forget to extend the yaml when extending 3PL
"""
start_time = time.time()
# with open("columns 1a.yaml", 'r') as f:
with open(os.path.join(os.path.dirname(__file__), 'columns 1a.yaml'), 'r') as f:
data = yaml.load(f, Loader=SafeLoader)
with tempfile.TemporaryDirectory() as tmpdirname:
try :
# create new list if there's new 3pl behavior (extend this)
list_type_like = [data['behavior']['type_like'][i]['name3pl'] for i in range(0,len(data['behavior']['type_like']))] #collects names of 3pl which have categorical column to be divided based on
write_eror_status = False
status = False
for i in range(0,len(data['behavior']['type_like'])):
if data['behavior']['type_like'][i]['name3pl']==self.name3pl: #get the name of category column and the values of categories (extend this whole if-statement)
list_types = data['behavior']['type_like'][i]['cats']
cat_column = data['behavior']['type_like'][i]['categorical_col']
status = True
else : pass
if status == False: #for logging to check if its in the list of type-like 3pl (extend this whole if else statement)
print("3PL cannot be found on type-like 3PL list")
else: print("3PL can be found on type-like 3PL list")
try:
for cat in list_types: #dynamic list creation for each category (extend this line only)
globals()[f"{cat}_final_df"] = []
except : print("3pl isn't split based on it's categories")
xl = win32com.client.Dispatch("Excel.Application")
print("Cast to CSV first (win32com)")
wb = xl.Workbooks.Open(self.filename,ReadOnly=1)
xl.DisplayAlerts = False
xl.Visible = False
xl.ScreenUpdating = False
xl.EnableEvents = False
sheet_names = [sheet.Name for sheet in wb.Sheets if sheet.Name.lower() != 'summary']
print("Sheet names")
print(sheet_names)
for sheet_name in sheet_names:
print("Reading sheet "+sheet_name)
ws = wb.Worksheets(sheet_name)
ws.SaveAs(tmpdirname+"\\myfile_tmp_{}.csv".format(sheet_name), 24)
used_columns = data['sls_data'][f'{self.name3pl.lower()}_used_columns']
renamed_columns = data['sls_data'][f'{self.name3pl.lower()}_rename_columns']
rowskip = data['behavior']['row_skip'][f'{self.name3pl.lower()}']
list_dtypes = [str for u in used_columns]
print("CP 1")
scandf = pl.scan_csv(tmpdirname+"\\myfile_tmp_{}.csv".format(sheet_name),skip_rows= rowskip,n_rows=10) #scan csv to get column name
print(scandf.columns)
scanned_cols = scandf.columns.copy()
used_cols_inDF = [] #collects column names dynamically
for i in range(0,len(used_columns)):
if type(used_columns[i]) is list: #check for each scanned-columns which contained in yaml used_columns, append if the scanned columns exist in yaml
for sc in scanned_cols:
for uc in used_columns[i]:
if sc == uc:
print(f"Column match : {uc}")
used_cols_inDF.append(uc)
else:pass
else:
for sc in scanned_cols: #purpose is same with the if statement
if sc == used_columns[i]:
print(f"Column match : {used_columns[i]}")
used_cols_inDF.append(used_columns[i])
else:pass
print(used_cols_inDF)
"""
JNT files have everchanging column names. Some files only have Total Ongkir, some only have Total,
and some might have Total and Total Ongkir. If both exists then will use column Total Ongkir (extend this if necessary i.e for special cases of 3pl)
"""
if self.name3pl == 'JNT':
if "Total" in used_cols_inDF and "Total Ongkir" in used_cols_inDF:
used_cols_inDF.remove("Total")
else:pass
else:pass
pldf_csv = pl.read_csv(tmpdirname+"\\myfile_tmp_{}.csv".format(sheet_name),
columns = used_cols_inDF,
new_columns = renamed_columns,
dtypes = list_dtypes,
skip_rows= rowskip
).filter(~pl.fold(acc=True, f=lambda acc, s: acc & s.is_null(), exprs=pl.all(),)) #filter rows with all null values
print(pldf_csv)
print(pldf_csv.columns)
for v in data['sls_data']['add_columns']: #create dynamic columns
if "3pl invoice distance (m) (optional)" in v.lower() or "3pl cod amount (optional)" in v.lower():
pldf_csv = pldf_csv.with_column(pl.Series(name="{}".format(v),values= np.zeros(shape=pldf_csv.shape[0])))
elif "3pl tn (mandatory)" in v.lower() or "weight (kg) (optional)" in v.lower():
pass
elif "total fee (3pl) (optional)" in v.lower():
pldf_csv = pldf_csv.with_column(pl.col(v).str.replace_all(",","").str.strip().cast(pl.Float64,False).fill_null(0))
else :
pldf_csv = pldf_csv.with_column(pl.lit(None).alias(v))
print(pldf_csv)
endpath = self.filedir+"\{}_{}_{}.csv".format(get_file_name(file_name_appear_label["text"]),sheet_name,"IngestResult").replace('/','\\')
if self.name3pl not in list_type_like: #(extend this line only)
if self.name3pl == 'JNT': #(extend this line and its statement if necessary i.e for special cases of 3pl)
pldf_csv = pldf_csv.with_column((pl.col("Total Fee (3PL) (Optional)")+pl.col("Biaya Asuransi").str.replace_all(",","").str.strip().cast(pl.Float64,False).fill_null(0)).alias("Total Fee (3PL) (Optional)"))
else: pass
print(pldf_csv)
try:
pldf_csv[data['sls_data']['add_columns']].write_csv(endpath,sep='\t')
except:
write_eror_status = True
print("CANNOT WRITE FILE")
elif self.name3pl in list_type_like: #(extend this line only)
for cat in list_types:
globals()[f"{cat}_final_df"].append(pldf_csv.filter(pl.col(cat_column).str.contains(cat)))
if self.name3pl not in list_type_like:
pass
elif self.name3pl in list_type_like:
for cat in list_types:
globals()[f"{cat}_final_df"] = pl.concat(globals()[f"{cat}_final_df"])
print(globals()[f"{cat}_final_df"])
globals()[f"endpath_{cat}"] = self.filedir+"\{}_{}_{}.csv".format(get_file_name(file_name_appear_label["text"]),cat,"IngestResult").replace('/','\\')
print("done creating paths")
try:
globals()[f"{cat}_final_df"][data['sls_data']['add_columns']].write_csv(globals()[f"endpath_{cat}"],sep='\t')
except :
write_eror_status = True
print("CANNOT WRITE FILE")
if write_eror_status == False:
progress_label["text"] = "Successful!"
else:
progress_label["text"] = "Cannot write result into Excel, please close related Excel files and kill Excel processes from Task Manager"
print("Process finished")
except Exception as e:
print("ERROR with message")
print(e)
progress_label["text"] = "Failed due to {}".format(e)
finally :
wb.Close(False)
submit_btn["state"] = "normal"
browse_btn["state"] = "normal"
print("Total exec time : {}".format((time.time()-start_time)/60))
def file_submit_btn_click():
if (file_name_appear_label["text"]==""):
progress_label["text"] = "Please input your file"
elif option_menu.get() == '':
progress_label["text"] = "Please select 3pl name"
else:
try :
submit_btn["state"] = "disabled"
browse_btn["state"] = "disabled"
progress_label["text"] = "Loading . . ."
name3pl = option_menu.get()
ingest = IngestGenerator(file_name,file_path,name3pl)
print(get_file_name(file_name_appear_label["text"]))
threading.Thread(target=ingest.generate_result_csv).start()
except Exception as e:
print(e)
Since the error was raised when writing CSV with polars and polars has its own dependencies, when it's in exe form it needs to include --recursive-copy-metadata as per documentation pyinstaller --recursive-copy-metadata polars --onefile -w "myfile.py"

How to run an .sql file full of commands as a command line argument to a python program?

I have a .sql file full of commands that I want to run through my python program. When I enter each line into the terminal individually, my program works as expected, as it has methods of parsing through the individual line entry to do what it needs to do. However, when I run the program (pa_2.py) by typing it into the terminal as such:
python3 pa_2.py < PA2_test.sql
the program doesn't read each line correctly and malfunctions, my guess being that it is unable to parse through the sql file correctly. The expected output is:
-- Database CS457_PA2 created.
-- Using database CS457_PA2.
-- Table Product created.
-- 1 new record inserted.
-- 1 new record inserted.
-- 1 new record inserted.
-- 1 new record inserted.
-- 1 new record inserted.
-- pid int|name varchar(20)|price float
-- 1|Gizmo|19.99
-- 2|PowerGizmo|29.99
-- 3|SingleTouch|149.99
-- 4|MultiTouch|199.99
-- 5|SuperGizmo|49.99
-- 1 record modified.
-- 2 records modified.
-- pid int|name varchar(20)|price float
-- 1|Gizmo|14.99
-- 2|PowerGizmo|29.99
-- 3|SingleTouch|149.99
-- 4|MultiTouch|199.99
-- 5|Gizmo|14.99
-- 2 records deleted.
-- 1 record deleted.
-- pid int|name varchar(20)|price float
-- 2|PowerGizmo|29.99
-- 3|SingleTouch|149.99
-- name varchar(20)|price float
-- SingleTouch|149.99
When I type each command as an individual line after typing in the terminal:
python3 pa_2.py
I get the expected output. However, when I run the script in the command line as:
python3 pa_2.py < PA2_test.sql
the output I get is:
created.CS457_PA2
because it does not exist.7_PA2
Created table Product.
1 new record inserted.
1 new record inserted.
1 new record inserted.
1 new record inserted.
1 new record inserted.
because it does not exist.uct
0 records modified.
0 records modified.
because it does not exist.uct
0 records modified.
Traceback (most recent call last):
File "/Users/isaac_reilly/Desktop/College/UNR/Classes/Year 3 2022-2023/Semester 1 2022/CS 457 Database Managemant Systems/Project 3/pa_2.py", line 79, in <module>
tablefunctions.deleteData(user_input, currentdb)
File "/Users/isaac_reilly/Desktop/College/UNR/Classes/Year 3 2022-2023/Semester 1 2022/CS 457 Database Managemant Systems/Project 3/tablefunctions.py", line 114, in deleteData
if float(splitter[4]) > float(searchText):
ValueError: could not convert string to float: '19.99)'
I want it to know that the end of each line is a semicolon ";". How would I use PA2_test.sql as a command line argument and run each line as expected? Below is the .sql file, as well as the rest of my program.
PA2_test.sql:
CREATE DATABASE CS457_PA2;
USE CS457_PA2;
CREATE TABLE Product (pid int, name varchar(20), price float);
INSERT INTO Product values(1, 'Gizmo', 19.99);
INSERT INTO Product values(2, 'PowerGizmo', 29.99);
INSERT INTO Product values(3, 'SingleTouch', 149.99);
INSERT INTO Product values(4, 'MultiTouch', 199.99);
INSERT INTO Product values(5, 'SuperGizmo', 49.99);
SELECT * FROM Product;
UPDATE Product set name = 'Gizmo' where name = 'SuperGizmo';
UPDATE Product set price = 14.99 where name = 'Gizmo';
SELECT * FROM Product;
DELETE FROM Product where name = 'Gizmo';
DELETE FROM Product where price > 150;
SELECT * FROM Product;
SELECT name, price FROM Product where pid != 2;
.EXIT
pa_2.py:
import fileinput
import sys
import dbfunctions
import tablefunctions
import selections
currentdb = None
user_input = None
TableList = [None]
#Loop continously prompts the terminal for an input from the user and then decides what to do based on input.
while (user_input != ".EXIT"):
user_input = input()
#print(user_input)
#States that all commands must end with a ';' if user types invalid command
if ";" not in user_input and user_input != ".EXIT":
print("Invalid command, all commands must end with ';'")
#Creates a database
if "CREATE DATABASE" in user_input:
dbName = dbfunctions.inputCleaner("CREATE DATABASE ", user_input)
dbfunctions.create_db(dbName)
#Deletes a database
if "DROP DATABASE" in user_input:
dbName = dbfunctions.inputCleaner("DROP DATABASE ", user_input)
dbfunctions.remove_db(dbName)
#Creates a table using attributes inputted by user
if "CREATE TABLE" in user_input:
tInput = dbfunctions.inputCleaner("CREATE TABLE ", user_input)
tableName = tInput.split()[0]
tablefunctions.createTable(tInput, tableName, currentdb)
#Deletes a table
if "DROP TABLE" in user_input:
tableName = dbfunctions.inputCleaner("DROP TABLE ", user_input)
tablefunctions.dropTable(tableName, currentdb)
#Modifies a table using attributes inputted by the user
if "ALTER TABLE" in user_input:
rawInput = dbfunctions.inputCleaner("ALTER TABLE ", user_input)
tablefunctions.alterTable(rawInput, currentdb)
#Sets current working database
if "USE" in user_input:
dbName = dbfunctions.inputCleaner("USE ", user_input)
#print(dbName)
currentdb = dbName
dbfunctions.finddb(currentdb)
#print("Using database " + currentdb)
#elif dbfunctions.finddb(currentdb) == 0:
#print("Unable to use database " + dbName + " because it does not exist.")
#Selects data from a user specified table and prints contents to terminal
if "SELECT" in user_input:
selections.selectSpecified(user_input, currentdb)
#Inserts given data into a specified table
if "INSERT INTO" in user_input:
dataInput = dbfunctions.inputCleaner("INSERT INTO ", user_input)
tableName = dataInput.split()[0]
tablefunctions.insertData(dataInput, tableName, currentdb)
#Changes data in table as specified
if "UPDATE" in user_input:
tablefunctions.updateData(user_input, currentdb)
#Deletes data from table as specified
if "DELETE FROM" in user_input:
tablefunctions.deleteData(user_input, currentdb)
dbfunctions.py:
import os
import subprocess
import shlex
import shutil
#Removes semicolon and given phrase from input
def inputCleaner(removePhrase, input):
cleaned = input.replace(";", "")
return cleaned.replace(removePhrase, "")
#Function used to create specified database (local directory)
def create_db(dbName):
try:
#Tries making directory
os.makedirs(dbName)
print("Database " + dbName + " created.")
except FileExistsError:
#Checks to see if directory already exists, throws exception if it does
print("!Failed to create database " + dbName + " because it already exists.")
#Function used to remove specified database (local directory)
def remove_db(dbName):
#Checks to see if specified directory exists and deletes if it does
if os.path.exists(dbName):
shutil.rmtree(dbName)
print("Database " + dbName + " deleted.")
#If selected directory does not exists, prints an error message to the screen
else:
print("!Failed to delete " + dbName + " because it does not exist.")
#Checks to make sure that specified database exists
def finddb(dbName):
if dbName in subprocess.run(['ls', '|', 'grep', dbName], capture_output = True, text = True).stdout:
print("Using database " + dbName)
else:
print("Unable to use database", dbName,"because it does not exist.")
def getOperand(op):
operand = None
if (op == '='):
operand = 0
elif (op == '!='):
operand = -3
elif (op == '<'):
operand = -1
elif (op == '>'):
operand = 1
return operand
tablefunctions.py:
import subprocess
import os
#Checks to make sure that specified table exists
def findtable(tableName, currentdb):
if tableName in subprocess.run(['ls', currentdb, '|', 'grep', tableName], capture_output = True, text = True).stdout:
return 1
else:
return 0
#Creates table with specified headers
def createTable(dataInput, tableName, currentdb):
unformattedAttributes = dataInput.replace(tableName, "")
tableAttributes1 = unformattedAttributes[2:]
tableAttributes2 = tableAttributes1[:-1]
formattedAttributes = tableAttributes2.split(",")
if (currentdb != None):
if findtable(tableName, currentdb) == 0:
os.system(f'touch {currentdb}/{tableName}.txt')
filename = currentdb + '/' + tableName + '.txt'
fedit = open(filename, 'w')
fedit.write(" |".join(formattedAttributes))
fedit.close()
print(f"Created table {tableName}.")
else:
print("!Failed to create table " + tableName + " because it already exists.")
else:
print("Please specify which database to use.")
#Deletes specified table
def dropTable(tableName, currentdb):
if (currentdb != None):
if findtable(tableName, currentdb) != 0:
os.system(f'rm {currentdb}/{tableName}.txt')
print("Table " + tableName + " deleted.")
else:
print("!Failed to delete " + tableName + " because it does not exist.")
else:
print("No specified database, enter 'USE <database_name>;'")
#Inserts data into specified table
def insertData(dataInput, tableName, currentdb):
unformattedInput = dataInput.replace(tableName, "")
cleanedInput1 = unformattedInput.replace("'", "")
cleanedInput2 = cleanedInput1.replace(" ", "")
unformattedAttributes = cleanedInput2[7:-1]
formattedAttributes = unformattedAttributes.split(",")
if (currentdb != None):
if findtable(tableName, currentdb):
fedit = open(f'{currentdb}/{tableName}.txt', 'a')
fedit.write("\n" + " | ".join(formattedAttributes))
fedit.close()
print("1 new record inserted.")
else:
print("!Failed to insert data into " + tableName + " because it does not exist.")
else:
print("No specified database, enter 'USE <database_name>;'")
#Modifies a table using attributes inputted by the user
def alterTable(rawInput, currentdb):
tableName = rawInput.split()[0]
alterCmd = rawInput.split()[1]
alterAttribute1 = rawInput.replace(tableName, "")
alterAttribute2 = alterAttribute1.replace(alterCmd, "")
newAttr = alterAttribute2[2:]
if (currentdb != None):
if findtable(tableName, currentdb):
fedit = open(f'{currentdb}/{tableName}.txt', 'a')
fedit.write(f" | {newAttr}")
fedit.close()
print("Table " + tableName + " modified.")
else:
print("!Failed to modify " + tableName + " because it does not exist.")
else:
print("No specified database, enter 'USE <database_name>;'")
#Removes data from specified table
def deleteData(user_input, currentdb):
if (currentdb != None):
cleanedInput1 = user_input[12:-1]
cleanedInput2 = cleanedInput1.replace("'", "")#Cleans input
tableName = cleanedInput2.split()[0]
if findtable(tableName, currentdb) != 0:
replaceText = ""
searchText = cleanedInput2.split()[4]
searchCategory = cleanedInput2.split()[2]
with open(f'{currentdb}/{tableName}.txt', 'r') as file:
count = 0
replacement = ""
if cleanedInput2.split()[3] == "=":
#Loops line by line for keywords
for line in file:
line = line.strip()
splitter = line.split()#Puts line into list elements
if searchText == splitter[2]: #If elements matches search text
updatedLine = "" #delete it
count += 1 #Keeps track of number of edits
else:
updatedLine = line + "\n" #Reads line unchanged if specified data is not present
replacement = replacement + updatedLine
if cleanedInput2.split()[3] == ">":
lineCount = 0
for line in file:
line = line.strip()
splitter = line.split()
if lineCount == 0:
lineCount += 1
updatedLine = line + "\n"
else:
if float(splitter[4]) > float(searchText):
updatedLine = ""
count += 1
else:
updatedLine = line + "\n"
replacement = replacement + updatedLine
if cleanedInput2.split()[3] == "<":
lineCount = 0
for line in file:
line = line.strip()
splitter = line.split()
if lineCount == 0:
lineCount += 1
updatedLine = line + "\n"
else:
if float(splitter[4]) < float(searchText):
updatedLine = ""
count += 1
else:
updatedLine = line + "\n"
replacement = replacement + updatedLine
file.close()
with open(f'{currentdb}/{tableName}.txt', 'w') as file:
file.write(replacement)
file.close()
if count == 1:
print(str(count) + " record modified.")
else:
print(str(count) + " records modified.")
else:
print("!Failed to update " + tableName + " table because it does not exist.")
else:
print("No specified database, enter 'USE <database_name>;'")
def updateData(user_input,currentdb):
if (currentdb != None):
cleanedInput1 = user_input[7:-1]
cleanedInput2 = cleanedInput1.replace("'", "")
tableName = cleanedInput2.split()[0]
if findtable(tableName, currentdb) != 0:
replaceText = cleanedInput2.split()[4]
searchText = cleanedInput2.split()[8]
replaceCategory = cleanedInput2.split()[2]
searchCategory = cleanedInput2.split()[6]
with open(f'{currentdb}/{tableName}.txt', 'r') as file:
count = 0
replacement = ""
if (replaceCategory == searchCategory):#if both columns being referenced are the same
for line in file:
line = line.strip()
if searchText in line:
updatedLine = line.replace(searchText, replaceText)
count += 1
else:
updatedLine = line
replacement = replacement + updatedLine + "\n"
else:
for line in file:
splitter = line.split()
splitter[4] = replaceText
line = line.strip()
if searchText == splitter[2]:
updatedLine = " ".join(splitter)
count += 1
else:
updatedLine = line
replacement = replacement + updatedLine + "\n"
file.close()
with open(f'{currentdb}/{tableName}.txt', 'w') as file:
file.write(replacement)
file.close()
if count == 1:
print(str(count) + " record modified.")
else:
print(str(count) + " records modified.")
else:
print("!Failed to update " + tableName + " table because it does not exist.")
else:
print("No specified database, enter 'USE <database_name>;'")
selections.py:
import tablefunctions
import dbfunctions
def selectAll(tableName, currentdb):
if currentdb == None:
print("No specified database, enter 'USE <database_name>;'")
else:
if tablefunctions.findtable(tableName, currentdb):
fedit = open(f'{currentdb}/{tableName}.txt', 'r')
print(fedit.read())
fedit.close()
else:
print("!Failed to query table " + tableName + " because it does not exist.")
def selectSpecified(user_input, currentdb):
if "SELECT * FROM" in user_input:
tableName = dbfunctions.inputCleaner("SELECT * FROM ", user_input)
selectAll(tableName, currentdb)
else:
if "SELECT" in user_input:
selLower = user_input[7:-1]
selection = user_input[7:-1]
elif "select" in user_input:
selection = user_input[7:-1]
# Gathering list of variables
selectColumns = selection.replace(",", "").split()
selectColumns = selectColumns[:selectColumns.index("FROM")]
# Table name
tableName = selection.split()[len(selectColumns)+1]
# Gathering what to filter by
whereColumn = selection.split()[len(selectColumns)+3]
whereRecord = selection.split()[len(selectColumns)+5]
operand = dbfunctions.getOperand(selection.split()[len(selectColumns)+4])
if currentdb != None:
if tablefunctions.findtable(tableName, currentdb):
f = open(f'{currentdb}/{tableName}.txt', 'r')
file = f.readlines()
f.close()
selectColumnNums = []
columnNameString = ""
listToReturn = []
count = 0
for line in file:
if (count == 0): # Headers
# Finding the indexes of select and where columns
columnList = line.split()
columnListWithTypes = columnList.copy()
del columnListWithTypes[2::3]
del columnList[1::3]
columnCount = 0
# If variable is found in table, record its index
for word in columnList:
if word in selectColumns:
selectColumnNums.append(columnCount)
if (word == whereColumn):
whereColumnNum = columnCount
columnCount += 1
# Creating a custom table header for the selected columns
for index in selectColumnNums:
columnNameString += f"{columnListWithTypes[index]} {columnListWithTypes[index+1]} | "
queryHeader = columnNameString[:-3]
listToReturn.append(queryHeader)
if (count > 0): # Values
tupleDetails = line.split()
# Determines what to do with each row
def querySpecificHelper():
# Creates the row output
def queryStringMaker():
queryString = ""
for index in selectColumnNums:
queryString += f"{tupleDetails[index]} | "
queryResult = queryString[:-3]
listToReturn.append(queryResult)
if (operand == 0): # Equality
# The type checking here handles strings and numbers separately
# Ex. 150 or 150.00 would not find 150.00 or 150, respectively
if (type(tupleDetails[whereColumnNum]) is str):
if (tupleDetails[whereColumnNum] == whereRecord):
queryStringMaker()
elif (type(tupleDetails[whereColumnNum]) is not str):
if (float(tupleDetails[whereColumnNum]) == float(whereRecord)):
queryStringMaker()
elif (operand == 1): # Greater than
if (float(tupleDetails[whereColumnNum]) > float(whereRecord)):
queryStringMaker()
elif (operand == -1): # Less than
if (float(tupleDetails[whereColumnNum]) < float(whereRecord)):
queryStringMaker()
elif (operand == -3): # Inequality
if (type(tupleDetails[whereColumnNum]) is str):
if (tupleDetails[whereColumnNum] != whereRecord):
queryStringMaker()
elif (type(tupleDetails[whereColumnNum]) is not str):
if (float(tupleDetails[whereColumnNum]) != float(whereRecord)):
queryStringMaker()
querySpecificHelper()
count += 1
for line in listToReturn: # Prints table
print(line)
else:
print(f"Could not query table {tableName} because it does not exist.")
else:
print("Please specify which database to use.")

TypeError: 'int' object is not iterable when executin SQL with SET in python3

I am creating set, to prevent duplicates while I am deleting old folders on server depending on status in column of table. But when I try to run this script
cursor = connection.cursor()
sql="SELECT id, name, state FROM domain WHERE state='2'"
cursor.execute(sql)
records = cursor.fetchall()
print("Total number of records for deleting is: ", cursor.rowcount)
deleted = set(cursor.execute("select distinct name from domain where state = 2"))
active = set(cursor.execute("select distinct name from domain where state != 2"))
to_delete = deleted - active
print('Printing each domain record', "\n")
for row in records:
print("id = ", row["id"], )
print("name = ", row["name"])
print("state = ", row["state"], "\n")
id = row["id"]
name = row["name"]
state = row["state"]
if to_delete == 2:
try:
if os.path.exists('/data/sa/' + name):
print('found records for deleting: ' + name, "\n")
print("Total number of records for deleting is: ", cursor.rowcount)
input("Press Enter to continue...")
shutil.rmtree('/data/sa/' + name)
print('records deleted')
else:
print('no Directory found')
# pass
except Exception as error:
print("Directory already deleted or never existed")
else:
print('no records for deleting found')
print('domain', name)
print('hast state', state, "\n")
quit()
connection.close()
I've to this error
Traceback (most recent call last):
File "mazani_old_zaznamu2.py", line 21, in <module>
deleted = set(cursor.execute("select distinct name from domain where state = 2"))
TypeError: 'int' object is not iterable
I asume that's because there is alot of domain rows, so I have to sort them somehow make iterable, but I dont know how is that possible.
The execute method doesn't return the rows itself, just the number of affected rows.
To get the results, try:
cursor.execute("select distinct name from domain where state = 2")
deleted = set(d['name'] for d in cursor.fetchall())

Reading from a CSV returns IndexError: list index out of range

I have a script that manages an employee database. After adding an employee record and appending a CSV file with the data, I close the program. Starting fresh, I try to import the CSV and it returns the error "IndexError: list index out of range."
After appending the csv and closing the program, I then open the csv using notpad++. In the file, two additional lines are added.
Using a try - except block, how can I delete rows from the CSV file?
In the add_employee function, can anyone see why it's adding two additional rows?
def import_employees():
with open('Employee_database.csv', 'r') as csvfile: #Opens the student answer file, and closes once finished
employee_reader = csv.reader(csvfile)
first_row = True
for row in employee_reader:
#Skip the first row with column names
if first_row:
first_row = False
continue
try:
fullName = row[0] + ' ' + row[1] #Creates full name for dictionary key
employeeList[fullName] = row
except IndexError:
del
def add_employee(): #CPT 200: Functionality 1 part 1
employeeFName = input("Please Emter the Employee #%d's First Name:" % num)
employeeLName = input("Please Enter the Employee #%d's Last Name:" % num)
employeeSSN = input("Please Enter %s %s's SSN (123456789):" % (employeeFName, employeeLName))
employeePhone = input("Please Enter %s %s's Phone Number:" % (employeeFName, employeeLName))
employeeEmail = input("Please Enter %s %s's Email Address:" % (employeeFName, employeeLName))
employeeSalary = input("Please Enter %s %s's Salary:" % (employeeFName, employeeLName))
employeeFull = employeeFName + ' ' + employeeLName
print(" ")
employeeInfo = [employeeFName.capitalize(), employeeLName.capitalize(), employeeSSN, employeePhone, employeeEmail, employeeSalary]
if (employeeFull and employeeSSN) not in employeeList.keys():
with open('Employee_database.csv', 'a+') as employeeCSV:
employee_writer = csv.writer(employeeCSV)
employee_writer.writerow(employeeInfo)
else:
print('Employee is already in the database, please try again.')
return employeeFull.upper(), employeeInfo

Import a CSV to Google Fusion Table with python

From http://fuzzytolerance.info/blog/2012/01/13/2012-01-14-updating-google-fusion-table-from-a-csv-file-using-python/ I have edited his code to import the necessary modules, however I get the following error "AttributeError: 'module' object has no attribute 'urlencode'". I run the code and I am prompted to enter my password, I enter my own google account password, and then the code gives me the error message, pehaps I need to define a password somewhere?
I wonder if anyone can please trouble shoot my code or advise me on how to avoid this error or even advise me of an EASIER way to import a CSV into a GOOGLE FUSION TABLE that I OWN
Here is my code
import csv
from decimal import *
import getpass
from fusiontables.authorization.clientlogin import ClientLogin
from fusiontables import ftclient
nameAgeNick = 'C:\\Users\\User\\Desktop\\NameAgeNickname.txt'
# check to see if something is an integer
def isInt(s):
try:
int(s)
return True
except ValueError:
return False
# check to see if something is a float
def isFloat(s):
try:
float(s)
return True
except ValueError:
return False
# open the CSV file
ifile = open(nameAgeNick, "rb")
reader = csv.reader(ifile)
# GFT table ID
tableID = "tableid"
# your username
username = "username"
# prompt for your password - you can hardcode it but this is more secure
password = getpass.getpass("Enter your password:")
# Get token and connect to GFT
token = ClientLogin().authorize(username, password)
ft_client = ftclient.ClientLoginFTClient(token)
# Loop through the CSV data and upload
# Assumptions for my data: if it's a float less than 0, it's a percentage
# Floats are being rounded to 1 significant digit
# Non-numbers are wrapped in a single quote for string-type in the updatate statement
# The first row is the column names and matches exactly the column names in Fustion tables
# The first column is the unique ID I'll use to select the record for updating in Fusion Tables
rownum = 0
setList = list()
nid = 0
for row in reader:
# Save header row.
if rownum == 0:
header = row
else:
colnum = 0
setList[:] = []
for col in row:
thedata = col
# This bit rounds numbers and turns numbers < 1 into percentages
if isFloat(thedata):
if isInt(thedata) is False:
if float(thedata) < 1:
thedata = float(thedata) * 100
thedata = round(float(thedata), 1)
else:
thedata = "'" + thedata + "'"
# make sql where clause for row
setList.append(header[colnum] + "=" + str(thedata))
nid = row[0]
colnum += 1
# get rowid and update the record
rowid = ft_client.query("select ROWID from " + tableID + " where ID = " + nid).split("\n")[1]
print( rowid)
print( ft_client.query("update " + tableID + " set " + ",".join(map(str, setList)) + " where rowid = '" + rowid + "'"))
rownum += 1
ifile.close()​
And this is the module where the error occurs:
#!/usr/bin/python
#
# Copyright (C) 2010 Google Inc.
""" ClientLogin.
"""
__author__ = 'kbrisbin#google.com (Kathryn Brisbin)'
import urllib, urllib2
class ClientLogin():
def authorize(self, username, password):
auth_uri = 'https://www.google.com/accounts/ClientLogin'
authreq_data = urllib.urlencode({ //////HERE IS ERROR
'Email': username,
'Passwd': password,
'service': 'fusiontables',
'accountType': 'HOSTED_OR_GOOGLE'})
auth_req = urllib2.Request(auth_uri, data=authreq_data)
auth_resp = urllib2.urlopen(auth_req)
auth_resp_body = auth_resp.read()
auth_resp_dict = dict(
x.split('=') for x in auth_resp_body.split('\n') if x)
return auth_resp_dict['Auth']
​

Categories