I have a python script that I want to perform an action for each row found in a table or report if no rows were found.
This is some dummy code for troubleshooting
cur_users = lv_pgsql.cursor()
cur_users.execute("select * from users where us_idno > 10")
for lr_users in cur_users:
print("ping")
I know I will be able to check if I attempt to store the results in an array like bellow
la_users = cur_users.fetchall()
if len(la_users) != 0:
print("ping")
But is it possible to check with the above code as well without using fetchall?
You can wrap your code in a try except block, thus if the cursor is None it will throw an error. Also by doing this you can capture other errors and handle them.
if cur_users.execute("select * from users where us_idno > 10").rowcount:
print "ping!"
should do what you want?
Related
I'm quite new to Python/Flask and am writing a little script for some home automation I'm playing with.
At the moment, there's a route in my script that gets run by a cron job. This sniffs for bluetooth packets to see who's in and who's out of the house so I can control the heating. There's a row in my table for each person and a status which is either In or Out.
This works perfectly.
I've got another route to read the values back and display either a green or red bar on my dashboard depending on if they're in or out.
It's reading the values and doing some logic that I'm having problems with.
If I get the status for a person and display it on my dashboard (created with an HTML template), the value it displays is:
('In',)
In the MySQL table it's just In - no quotes or parentheses.
In my Python script I have:
conn = MySQLdb.connect(host="localhost", user = "*****", passwd = "*****", db = "mydb")
cursor = conn.cursor()
cursor.execute("select status from occupants WHERE id = '1'")
data = cursor.fetchone()
result = data
#result = str(result)
if (result == "In"):
result = "In"
else:
result = "Out"
This always returns Out.
I've tried various things in my if statement but I obviously haven't hit the right one. I've even tried:
if (result == "('In',)")
But even this returns Out.
Starting to tear my hair out now as I've been searching and playing for about 2 days just on this.
Any ideas gratefully received!
You need to get the value by index.
Python returns tuples for the rows.You need to get the first column.
Just get the value by index, data[0]
Then you go on with comparison.
Edit: when you use the "in" operators, you are just looping through the tuple.
It works buts not a good idea, when you already know for sure, the data you are looking for is at index 0.
You are using cursor.fetchone(), which returns a tuple or None(if element not found). So what you are receiving after executing the command is a tuple with only one element, which makes lesser sense in this context, but that is how this Python API returns data. So even after using fetchone() you need to access the first element explicitly, which can be done as lst[0]. So you need to change the line as:
result = ""
if data is not None:
result = data[0]
print result
You have more Data in "result" then just "In". For example:
a = ["yes", "hello"]
b = "no"
if "yes" == a:
print("yes yes yes")
else:
print("Something is wrong")
This gives you "Something is wrong" as output, but if you do:
a = ["yes", "hello"]
b = "no"
if "yes" in a:
print("yes yes yes")
else:
print("Something is wrong")
Now you get "yes yes yes" as output. Hope this helps a bit :)
Agree with Abhijith; indexing would be a better idea.
It's likely the result of you database query should look like this:
database_query_result = [('In',)]
If that's the case, you could just grab the occupants status like the below to get the answer you desire without a logical comparison.
result = database_query_result[0][0]
print(result)
Why this works:
database_query_result[0] gives you the tuple -> ('In', )
database_query_result[0][0] gives you the tuple's value. -> 'In'
Ok, as always, 5 minutes after posting, I try something different and get it working. However, I'm not sure if this is a fudge or if it's a valid thing to do:
if 'In' in result:
This now works.
For the purposes of this exercise, it doesn't really matter if it's a dirty workround but I'd like to know if there's a more elegant/conventional solution just for my learning.
Problem
I am connecting with JayDeBeApi to SQL Server 2017 and running a script like:
SELECT ... INTO #a-temp-table
DELETE FROM a-table
INSERT INTO a-table SELECT FROM #a-temp-table
DELETE #a-temp-table
During step 3 i get the following error:
Cannot insert duplicate key row in object 'dbo.a-table' with unique index 'UQ_a-table'. The duplicate key value is (11, 0001, 3751191, T70206CAT, 0000).
Instead of ~360k records, only ~180k get inserted. So step 3 aborts.
The temp table however gets deleted. So step 4 completes.
I am able to fix the error. But with JayDeBeApi, I am not seeing the error.
It seems like everything went fine from the Python point of view.
My goal is to capture those errors to handle them appropriately.
Any idea how to achieve that?
What I've tried
My Python code looks like.
try:
localCursor = dbConnection.cursor()
x = localCursor.execute(query)
logInfo("Run script %s... done" % (scriptNameAndPath), "run script", diagnosticLog)
except Exception as e:
logError("Error running sql statement " + scriptNameAndPath + ". Skipping rest of row.",
"run script", e, diagnosticLog)
myrow = skipRowAndLogRecord(startRowTime, cursor, recordLog)
continue
x = localCursor.execute(myqrystm) completes successfully, so no exception is thrown. x is None and while inspecting localCursor, I see no sign of any error message(s)/code(s)
Step 3 should be all-or-none so the a-table should be empty following the duplicate key error unless your actual code has a WHERE clause.
Regarding the undetected exception, add SET NOCOUNT ON as the first statement in the script. That will suppress DONE_IN_PROC messages that will interfere with script execution unless your code handles multiple result sets.
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql?view=sql-server-2017
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
GO
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
I've got a List like:
results = ['SDV_GAMMA','SDV_BETA,'...','...']
and then comes and for loop like:
for i in range (len(results)):
a = instance.elementSets[results[i]]
The strings defined in the result-list are part of a *.odb result file and if they didn't exist there comes an error.
I would like that my program doesn't stop cause of an error. It should go on and check if values of the others result values exist.
So i do not have to sort every result before i start my program. If it´s not in the list, there is no problem, and if it exists i get my data.
I hope u know what i mean.
You can use try..except block
Ex:
for i in results
try:
a = instance.elementSets[results[i]]
except:
pass
You can simply check the presence of results[i] in instance.elementSets before extracting it.
If instance.elementSets is a dictionary, use the dict.get command.
https://docs.python.org/3/library/stdtypes.html#dict.get
I am having the following python block where i want to check if a change doesnt exist in invalid_change and changes_not_in_manifest lists,the problem I am facing is as soon as the try loop is entered and checked for
invalid_change.index(change) it goes to except,how do I check if a change is not present in both "invalid_change" and "changes_not_in_manifest" lists?
try: # check if invalid change is present
invalid_change.index(change)
changes_not_in_manifest.index(change)
print "invalid list"
ifvalid = False
break
except:
print "except"
pass
Normally this kind of test is done using the in keyword:
if change not in invalid_change and change not in changes_not_in_manifest:
print "invalid list"
However, I think you are overlooking a good use case for sets. I have written a pretty detailed breakdown of a problem similar to this in this answer.
Basically, you would write a set comprehension like:
invalid_changes = {c for c in changes if c not in invalid_change or c not in manifest}
which you would later check using:
if change in invalid_changes:
# do something
I use SPARQLWrapper in python to query a web enpoint with many different querys in a loop.
So I tried to make it work like this (let queries hold all different queries and result the results):
sparql = SPARQLWrapper("url")
prefix = "prefix..."
for i in arange(1:len(queries)):
sparql.setQuery(prefix+queries[i])
result[i] = sparql.query().convert()
But this does not work. The first query I pick from the list would return the supposed result, but any other querys wouldn't.
Instead of that, I now use this:
for i in arange(1:len(queries)):
[sparql,prefix] = initializeSPARQL()
sparql.setQuery(prefix+queries[i])
result[i] = sparql.query().convert()
and also
def initializeSPARQL():
sparql = SPARQLWrapper("url")
prefix = "prefix..."
return sparql,prefix
That works and is also not an issue of performance, since the querying itself is the bottleneck. But is there a better solution? This appears to be so wrong...
It is strange.. because I've been checking the code, and the query() method is completely stateless, so no idea why it's failing.
With i > 1, what does result[i] contains?
May I suggest you to try the following?
sparql = SPARQLWrapper("url")
prefix = "prefix..."
results = []
for i in range(0, len(queries)):
sparql.resetQuery()
sparql.setQuery(prefix+queries[i])
results[i] = sparql.query().convert()
I'm one of the developers of the library.
Your first try arises a bug. I'll check what internal data structure keeps with the previous usage to allow such way to use the library.
You second solution, even if is works, should be not the right way to do it.
As I said, I'll take a look on how to fix this.
For the future, please, submit a proper bug report to the project or an email to the mailing list.