Index Out of Range on Tuple Integer Converted To String - python-2.7

I'm trying to print the last digit of an integer that's been pulled from a database and converted to a string. normally, this code works fine to print the last character of a string even if its a number thats been coverted to a string:
x = 225
print x[-1]
5
However, when I try to do the same thing on a value thats been pulled from a database, the Python interpreter gives me a string index out of range error.
Here is my code:
import MySQLdb
#mysql card_numbercheck
class NumberCheck(object):
def __init__(self):
self.conn = MySQLdb.connect(host='localhost', user='root', passwd='', db='mscan')
self.c = self.conn.cursor()
def query(self, arg, cardname):
self.c.execute(arg, cardname)
return self.c
def __del__(self):
self.conn.close()
# Define SQL statement to select all Data from Column Name
sql = "SELECT card_number FROM inventory_2 WHERE card_name = %s"
#Connect To DB and Get Number of Card.
def Get_MTG_Number():
global card_number
MtgNumber = NumberCheck()
for number in MtgNumber.query(sql, 'Anathemancer'):
card_number = str(number[0])
print card_number[-1]
Get_MTG_Number()
Logically, I don't really understand why this code wouldn't work. Any help would be highly appreciated.
Kind Regards
Jack

Maybe some of the data fields are blank, and by converting to a string you are just getting an empty string? Trying to index such a string will give you an 'index out of range' error.
To see what is going on, you could simply print card_number upon each iteration of the loop. You could also do with a bit more error handling to sanitize the data you are getting from a database.

Related

When I try to print(query) , I get the result as <pymongo.cursor.Cursor object at 0x00000273CCF21D90>

When I try to print(query), I get the result as <pymongo.cursor.Cursor object at 0x00000273CCF21D90> whereas I want the entire document that contains primaryTitle that has "Friday Night". Please help.
rgx = re.compile('.*Friday Night.*', re.IGNORECASE) # compile the regex
query= db.IllegalCollect.find({"$primaryTitle": rgx})
find() returns a cursor which you have to iterate to get the results; you can't just print the result as you have found. Your options are to use find_one() (will only return one record though); to use list(query) to convert to a list, or to iterate the cursor with a for loop.
The example below shows each method.
btw your $primaryTitle field in the find query won't work; you likely need primaryTitle without the $
import pymongo
import re
db = pymongo.MongoClient()['mydatabase']
db.IllegalCollect.insert_one({'primaryTitle': 'Last Friday Night, Yeah we maxed our credit cards'})
db.IllegalCollect.insert_one({'primaryTitle': 'And got kicked out of the bar, So we hit the boulevard'})
rgx = re.compile('.*Friday Night.*', re.IGNORECASE) # compile the regex
query = db.IllegalCollect.find_one({'primaryTitle': rgx})
print (query)
query = db.IllegalCollect.find({'primaryTitle': rgx})
print (list(query))
query = db.IllegalCollect.find({'primaryTitle': rgx})
for item in query:
print (item)

regex year format authentication

I have a program where the user is asked for the session year which needs to be in the form of 20XX-20XX. The constraint here is that it needs to be a year followed by its next year. Eg. 2019-2020.
For example,
Vaild Formats:
2019-2020
2018-2019
2000-2001
Invalid Fromats:
2019-2021
2000-2000
2019-2018
I am trying to validate this input using regular expressions.
My work:
import re
def add_pages(matchObject):
return "{0:0=3d}".format(int(matchObject) + 1)
try:
a = input("Enter Session")
p = r'2([0-9]{3})-2'
p1= re.compile(p)
x=add_pages(p1.findall(a)[0])
p2 = r'2([0-9]{3})-2'+x
p3 = re.compile(p2)
l=p3.findall(a)
if not l:
raise Exception
else:
print("Authenticated")
except Exception as e:
print("Enter session. Eg. 2019-2020")
Question:
So far I have not been able to retrieve a single regex that will validate this input. I did have a look at backreferencing in regex but it only solved half my query. I am looking for ways to improve this authentication process. Is there any single regex statement that will check for this constraint? Let me know if you need any more information.
Do you really need to get the session year in one input?
I think its better to have two inputs (or just automatically set the session year to be the first year + 1).
I don't know if you're aiming for something bigger and this is just an example but using regex just doesn't seem appropriate for this task to me.
For example you could do this:
print("Enter session year")
first_year = int(input("First year: "))
second_year = int(input("Second year: "))
if second_year != (first_year + 1):
# some validation
else:
# program continues
First of all, why regex? Regex is terrible at math. It would be easier to do something like:
def check_years(string):
string = "2011-2012"
years = string.split("-")
return int(years[0]) == (int(years[1]) - 1)

Python, is there a easier way to add values to a default key?

The program I am working does the following:
Grabs stdout from a .perl program
Builds a nested dict from the output
I'm using the AutoVivification approach found here to build a default nested dictionary. I'm using this method of defaultdict because it's easier for me to follow as a new programmer.
I'd like to add one key value to a declared key per pass of the for line in the below code. Is there a easier way to add values to a key beyond making a [list] of values then adding said values as a group?
import pprint
class Vividict(dict):
def __missing__(self, key):
value = self[key] = type(self)()
return value
reg = 'NtUser'
od = Vividict()
od[reg]
def run_rip():
os.chdir('/Users/ME/PycharmProjects/RegRipper2.8') # Path to regripper dir
for k in ntDict:
run_command = "".join(["./rip.pl", " -r
/Users/ME/Desktop/Reg/NTUSER.DAT -p ", str(k)])
process = subprocess.Popen(run_command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = process.communicate() # wait for the process to terminate
parse(out)
# errcode = process.returncode // used in future for errorcode checking
ntDict.popitem(last=False)
def parse(data):
pattern = re.compile('lastwrite|(\d{2}:\d{2}:\d{2})|alert|trust|Value')
grouping = re.compile('(?P<first>.+?)(\n)(?P<second>.+?)
([\n]{2})(?P<rest>.+[\n])', re.MULTILINE | re.DOTALL)
if pattern.findall(data):
match = re.search(grouping, data)
global first
first = re.sub("\s\s+", " ", match.group('first'))
od[reg][first]
second = re.sub("\s\s+", " ", match.group('second'))
parse_sec(second)
def parse_sec(data):
pattern = re.compile(r'^(\(.*?\)) (.*)$')
date = re.compile(r'(.*?\s)(.*\d{2}:\d{2}:\d{2}.*)$')
try:
if pattern.match(data):
result = pattern.match(data)
hive = result.group(1)
od[reg][first]['Hive'] = hive
desc = result.group(2)
od[reg][first]['Description'] = desc
elif date.match(data):
result = date.match(data)
hive = result.group(1)
od[reg][first]['Hive'] = hive
time = result.group(2)
od[reg][first]['Timestamp'] = time
else:
od[reg][first]['Finding'] = data
except IndexError:
print('error w/pattern match')
run_rip()
pprint.pprint(od)
Sample Input:
bitbucket_user v.20091020
(NTUSER.DAT) TEST - Get user BitBucket values
Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket
LastWrite Time Sat Nov 28 03:06:35 2015 (UTC)
Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\Volume
LastWrite Time = Sat Nov 28 16:00:16 2015 (UTC)
If I understand your question correctly, you want to change the lines where you're actually adding values to your dictionary (e.g. the od[reg][first]['Hive'] = hive line and the similar one for desc and time) to create a list for each reg and first value and then extend that list with each item being added. Your dictionary subclass takes care of creating the nested dictionaries for you, but it won't build a list at the end.
I think the best way to do this is to use the setdefault method on the inner dictionary:
od[reg][first].setdefault("Hive", []).append(hive)
The setdefault will add the second value (the "default", here an empty list) to the dictionary if the first argument doesn't exist as a key. It preempts the dictionary's __missing__ method creating the item, which is good, since we want a the value to be list rather than another layer of dictionary. The method returns the value for the key in all cases (whether it added a new value or if there was one already), so we can chain it with append to add our new hive value to the list.

Python csv file determine data type

new student here so please excuse my ignorance, I have searched a lot and not found a solution to my problem. I am needing to import a CSV file with mixed data types [ int, float, and string], determine the data type, then do maths on the ints and floats.
The problem is that csv reader converts everything to strings ( or they are already strings?). I can try and convert to float, and if it throws an error message I know it is a string, but how would I tell if it is a float, as my program needs to determine between the two?
I am only allowed to import CSV and no others. This is my second first-year python subject, and really not sure how to do this.
Edit, found one answer that seems similar to my problem, but it still returns the wrong answers, ints are usually, but not always, still returned as string type:
import csv
tests = [
# (Type, Test)
(int, int),
(float, float),
]
def getType(value):
for typ, test in tests:
try:
test(value)
return typ
except ValueError:
print 'value error'
continue
# No match
return str
file = open('adult.csv')
reader = csv.reader(file)
filename = 'output.xml'
text = open(filename, 'w')
text.write('<?xml version="1.0"?>')
text.write('<!DOCTYPE summary [')
headers = reader.next()
for i in headers:
print '<name>'
print i
print '</name>'
print '<dataType>'
for a in i[1]:
print getType[a]
#for row in fields:
# text = row[2]
# print type(text)
print '</dataType>'
#for value in i:
# print type(value)
print '<!ELEMENT summary\n\n>'
#text.write('<element>')
Ok sorry everybody, think i found some code i think will work:
determine the type of a value which is represented as string in python
SHOULD have searched harder, although still not reliably giving the correct type

Errors in Decimal Calcs within def clean method?

I'm attempting a few simple calculations in a def clean method following validation (basically spitting out a euro conversion of retrieved uk product price on the fly). I keep getting a TypeError.
Full error reads:
Cannot convert {'product': , 'invoice': , 'order_discount': Decimal("0.00"), 'order_price': {...}, 'order_adjust': None, 'order_value': None, 'DELETE': False, 'id': 92, 'quantity': 8} to Decimal
so I guess django is passing through the entire cleaned_data form to Decimal method. Not sure where I'm going wrong - the code I'm working with is:
def clean_order_price(self):
cleaned_data = self.cleaned_data
data = self.data
order_price = cleaned_data.get("order_price")
if not order_price:
try:
existing_price = ProductCostPrice.objects.get(supplier=data['supplier'], product_id=cleaned_data['product'], is_latest=True)
except ProductCostPrice.DoesNotExist:
existing_price = None
if not existing_price:
raise forms.ValidationError('No match found, please enter new price')
else:
if data['invoice_type'] == 1:
return existing_price.cost_price_gross
elif data['invoice_type'] == 2:
exchange = EuroExchangeRate.objects.latest('exchange_date')
calc = exchange.exchange_rate * float(existing_price.cost_price_gross)
calc = Decimal(str(calc))
return calc
return cleaned_data
If the invoice is of type 2 (a euro invoice) then the system should grab the latest exchange rate and apply that to the matching UK pound price pulled through to get euro result.
Should performing a decimal conversion be a problem within def clean method?
Thanks
I'm going to assume you've made an indentation error on pasting, and the lines from if data['invoice_type'] == 1: should actually be indented one level back - otherwise, as Alex says, the code will never get to the Decimal conversion.
There are multiple other problems with this code, but the biggest is that the last line returns the whole cleaned_data dictionary, rather than the value of this particular field - I suspect this is the cause of the error you are seeing.
Other than that, there is a big error where you calculate calc by multiplying cost_price_gross by exchange. Here exchange is an instance of EuroExchangeRate, rather than a number, so this calculation will not work.