Decrement a variable in an incrementing for loop - python

In my python script, I am itterating through a list (headerRow) starting at index 9. I want to check to see if it is already in the database, and if not then add it to a database with an auto-incementing primary key. I then want to send it through the loop again to retrieve it's primary key.
for i in range (9, len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
print i
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
i -= 1 # This was done so that it reiterates through and can get the PK next time.
print i
else: # Entry already exists
print "Existing Entry"
qpID = row[0]
# ...
Here is the output of my script:
9
New Question Added!
8
10
New Question Added!
9
11
As you can see, my issue is that range() doesn't care what the existing value of i is. What is the preferred python way to do what I'm trying to do?
Thanks in advance,
Mike

Why not use a while loop?
i=9
while (i<len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
else: # Entry already exists
print "Existing Entry"
qpID = row[0]
i += 1
# ...

My great distaste for manually changing index variables makes me want to comment on this... :)
How about just changing it to do both things in the same iteration?
Code looks a little strange, but you get the idea.
for i in range (9, len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
print i
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
row = cursor.fetchone() # re-fetch to get the PK
# Entry will exist now
print "Getting Existing Entry"
qpID = row[0]
# ...
And to try to explain why decrementing the "i" doesn't work:
The for loop doesn't really increment the variable. It simply picks the next value from the sequence you gave it (generated by the range function). So if the secquence is [9,10,11,12] it will pick those, in order. The variable "i" will get the next value and the previous will be discarded. No increment or decrement will affect this.

Related

Retrieve data from sql database using python

I'm a newbie for python and SQL.
My database contain a field which stored path to images.
I want to assign each path to a variable in python.
I can only store only the path of first row.
This is my code
import pymysql
from arcpy import env
env.workspace = "D:/year 4 semester 1/Python/Data/"
conn= pymysql.connect(host='localhost',user='root',password='',db='research')
cursor = conn.cursor ()
cursor.execute ("select Path from sourcedata")
data = cursor.fetchmany()
for row in data :
a= row[0]
print a
But when I try following way including all other relevant text
for row in data :
a= row[0]
b = row[1]
c = row[2]
print a
Following error appear
IndexError: tuple index out of range
you need to indent the print a statement to make it part of the loop. Python is very sensitive about indentation. In other languages you use braces or BEGIN END blocks, but in python you use indentation.
The row[0], row[1] stuff refers to the elements within the retrieved row, not the different rows.
indent the print line and it will print the first returned field, Path, for each record.
The tuple index is out of range because there is only one field (element zero) returned.
Your current code will iterate through every row returned and set a to each one in turn, but will only print the last value for a after it comes out of the loop.

Python: how to Add DictReader row as dictionary to list with an update

My code basically just goes thru checking each row of a DictReader (a list of dicts) and puts duplicates in the RejectedEvents list of dicts and returns result, which is a deduplicated dict of dicts. I also need to add a reason to each row of RejectedEvents because I will later be rejecting for other reasons as well. The code is pretty self explanatory as is the problem, but not the solution; The issue is the line marked #PROBLEM, and the problem disappears when I take out the update statement; with the update statement, null is assigned and without it row is assigned, so the update is messing it up.
def GetScrubbedEventData(MetricID, EventsRaw, RejectEvents):
start = time.time()
pass_count = 0
fail_count = 0
result = {}
for row in csv.DictReader(EventsRaw, delimiter=","):
try:
#check duplicate
result[row['AssetID']]
Reason = {"RejectedFor": "Duplicate AssetID in same file."}
RejectEvents.append(dict(row).update(Reason)) #PROBLEM
fail_count += 1
except KeyError:
row['EventStart'] = scrub.Date(row['EventStart'])
row['EventEnd'] = scrub.Date(row['EventEnd'])
result[row['AssetID']] = row
pass_count += 1
Update the row and then append the updated row, not the return value of .update which is None:
for row in csv.DictReader(EventsRaw):
...
row.update(Reason)
RejectEvents.append(row)
Or you can set a new directly on dict row without having to create the single-valued dict Reason:
for row in csv.DictReader(EventsRaw):
...
row["RejectedFor"] = "Duplicate AssetID in same file."
RejectEvents.append(row)

Need to display a text list of records not on my list

I need to search a feature class for multiple text entries and display all the values and their object ids that aren't on the list, i.e. find all the mistakes. (Basically, want to search for text entries such as AVE, TRL, ST, and display entries that aren't formatted like that). I want to write it in python.
Can I use the searchCursor to do this, or is it something more complicated.
Any help would be appreciated, Thanks! I think this is the solution, but it is still printing AVE. Any idea as to why?
import arcpy
fc = "Z:\Street_Centerlines"
field = "StSuffix"
field1 = "OBJECTID"
cursor = arcpy.SearchCursor(fc)
for row in cursor:
if field == "AVE":
pass
else:
print(row.getValue(field1)); print(row.getValue(field))
The field variable is equal to "StSuffix", so field == "AVE" is always false. I think you want this:
valid_values = 'AVE', 'TRL', 'ST'
for row in cursor:
value = row.getValue(field)
if value in valid_values:
continue
print("Invalid value: OBJECTID={}, StSuffix={}".format(
row.getValue(field1),
value
))

How to *append* a text to a database file opened with shelve?

After we create a database file using shelve.open and then close the program, if we run the code again, but with different input(s), it actually replaces the text instead of appending it.
How may I change this behavior?
For example:
db = shelve.open('store')
db['some variable'] = some value
db['another variable'] = another value
db.close()
And now when we write the same code but with different values for the same variable, we replace the previous value instead of appending the values to it. How can I change that?
Assuming your values are lists:
Use db = shelve.open('store',writeback=True) and then append the value to the same key.
Since your code does not open 'store' with writeback=True you
must assign a variable the value of the key, temp = db['some variable'], which would be
some value, and then append that variable, temp.append(another
value), and then reassign that keys value, db['some variable'] =
temp.
Should not your third line of code be db['some variable'] = another value' in order to replace the value?
Edit: Other possible meaning of question?
Do you mean you want to load the database into your object and continue to use your "UI" code to edit it after closing the program? If so then you can do something like:
class Update_MyStore(MyStore):
def __init__(self, store):
db = shelve.open(store)
for i in db:
setattr(self, i, db[i])
self.items()
self.store_in_db()
Update_MyStore('store')
Edit: Another option to update, if that is the case, if you want to add or update specific items:
while True:
store = shelve.open('store',writeback = True)
Item = input('Enter an item: ').capitalize() #I prefer str(raw_input('Question '))
if not Item or Item == 'Break':
break
store['item_quantity'][Item] = int(input(('Enter the number of {0} available in the store: ').format(Item)))
store['item_rate'][Item] = float(input(('Enter the rate of {0}: ').format(Item)))
store.sync()
store.close()

Why is python dictionary not refilling in while loop?

I've got a database that I loop through, and based on certain conditions, I send the relevant database entries to a dictionary that I created. I then want to pick one randomly from this dictionary, store it in a list, clear the dictionary, and do the whole thing again with incremented variables. FYI, the ['StartNoteNum'], etc. are just column names within the cost database.
What happens though, is that it works fine the first time thorough the loop, but if I try to clear the dictionary anywhere in the code (inside or outside the while loop), then the dictionary never re-fills based on the incremented values even though it should. To confirm that it should re-fill properly, I have set the initial values to be all possible values that it would encounter in the while loop, and each one works the first time through the loop, but fails once it tries to cycle. The error I get is that the random function can't pull from an empty dictionary. Grr... here is the code.
def compute_policy(clean_midi, cost_database):
note = 0 #Setting up starting variables.
total_score = []
current_finger = 1
path = [1]
next_move = {}
while note <= 2:
current_note = clean_midi[note] #get note-pair for scoring
dest_note = clean_midi[note+1]
for each in cost_database: #find all relevant DB entries
if (int(each['StartNoteNum']) == current_note
and int(each['DestNoteNum']) == dest_note
and int(each['StartFing']) == current_finger):
next_move[int(each['DestFing'])] = int(each['Score']) #move relevant entries to separate "bin"
policy_choice = random.choice(next_move.keys()) #choose one at random
total_score.append(next_move[policy_choice]) #track the scores for each choice in a list
path.append(policy_choice) #track the chosen finger
current_finger = policy_choice #update finger variable
note += 1
path.append(current_finger) #append last finger since the loop won't run again
return total_score, path
any help here would be much appreciated. Thanks.
You are trying to use the cost_database iterator twice. After the first time you pass through it is exhausted and thus the second time you try to use it the whole for loop is skipped because it got an empty iterator.
>>> a = xrange(4)
>>> for i in a:
... print(i)
0
1
2
3
4
>>> for i in a:
... print(i)
>>> # Nothing since 'a' is already exhausted.
One possible issue is:
int(each['DestFing']) is always the same, then the same key in the dictionary will get updated and count will stay 1.

Categories

Resources