First let me state that I am not a developer and have no formal training. I have a little experience with Python and have written scripts for telecom reporting. I'm working on a script that queries a database to determine the number of times a keypad was pressed. For example, key 1 was pressed 100 times, key 2 was pressed 300 times and so forth. I've been able to successfully retrieve the data and when I use the print function it works fine. However, when I attempt to take that same data and get it into the body of an email, it only seems to show the second index and not the first. Can someone help me understand why this happens and suggest how to correct? My for loop is indented, my email code is not. I've tried changing indenting and end up with two incorrect emails instead of one.
for row in data:
rowtolist = [elem for elem in row]
buttonkey = rowtolist[0]
timespressed = rowtolist[1]
data1 = 'Button {} was pressed {} times'.format(buttonkey,timespressed)
print(data1)
Output is:
Button 1 was pressed 710 times
Button 2 was pressed 1353 times
but when I attempt to take this data and add it to an email with this:
SERVER = "smtp.server"
FROM = "mysmtpserver"
TO = ["testemailaddress"]
SUBJECT = "Cisco Unity Report"
TEXT = data
message = """From: %s\r\nTo: %s\r\nSubject: %s\r\n\
%s\r\n
""" %(FROM, ",".join(TO), SUBJECT, TEXT)
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
cursor.close()
I get this in my email body :
Button 2 was pressed 1353 times
I'd like to know why I cannot get the same info as if I am using the print function.
I presume data and data1 are same.
You need to store the result of each iteration as follows,
results = list()
for row in data:
rowtolist = [elem for elem in row]
buttonkey = rowtolist[0]
timespressed = rowtolist[1]
data = f'Button {buttonkey} was pressed {timespressed} times'
results.append(data)
Then you can attach the result to the mail body as follows,
TEXT = "\n".join(results)
Related
I have just started learning python and i have been given an assignment to create a list of players and stats using different loops.
I cant work out how to create a function that searches the player list and gives an output of the players name and the players stat.
Here is the assignment:
Create an empty list called players
Use two input() statements inside a for loop to collect the name
and performance of each player (the name will be in the form of a
string and the performance as an integer from 0 – 100.) Add both
pieces of information to the list (so in the first iteration of the
loop players[0] will contain the name of the first player and
players[1] will contain their performance.) You are not required to
validate this data.
Use a while loop to display all the player information in the
following form:
Player : Performance
Use a loop type of your choice to copy the performance values from
the players list and store these items in a new list called results
Write a function that accepts the values “max” or “min” and
returns the maximum or minimum values from the results list
Write a function called find_player() that accepts a player name
and displays their name and performance from the players list, or an
error message if the player is not found.
Here is what I have so far:
print ("Enter 11 Player names and stats")
# Create player list
playerlist = []
# Create results list
results = []
# for loop setting amount of players and collecting input/appending list
for i in range(11):
player = (input("Player name: "))
playerlist.append(player)
stats = int(input("Player stats: "))
playerlist.append(stats)
# While loop printing player list
whileLoop = True
while whileLoop == True:
print (playerlist)
break
# for loop append results list, [start:stop:step]
for i in range(11):
results.append(playerlist[1::2])
break
# max in a custom function
def getMax(results):
results = (playerlist[1::2])
return max(results)
print ("Max Stat",getMax(results))
# custom function to find player
def find_player(playerlist):
list = playerlist
name = str(input("Search keyword: "))
return (name)
for s in list:
if name in str(s):
return (s)
print (find_player(playerlist))
I have tried many different ways to create the find player function without success.
I think I am having problems because my list consists of strings and integers eg. ['john', 6, 'bill', 8]
I would like it to display the player that was searched for and the stats ['John', 6]
Any help would be greatly appreciated.
PS:
I know there is no need for all these loops but that is what the assignment seems to be asking for.
Thank you
I cut down on the fat and made a "dummy list", but your find_player function seems to work well, once you remove the first return statement! Once you return something, the function just ends.
All it needs is to also display the performance like so:
# Create player list
playerlist = ["a", 1, "b", 2, "c", 3]
# custom function to find player
def find_player(playerlist):
name = str(input("Search keyword: "))
searchIndex = 0
for s in playerlist:
try:
if name == str(s):
return ("Player: '%s' with performance %d" % (name, playerlist[searchIndex+1]))
except Exception as e:
print(e)
searchIndex += 1
print (find_player(playerlist))
>>Search keyword: a
>>Player: 'a' with performance 1
I also added a try/except in case something goes wrong.
Also: NEVER USE "LIST" AS A VARIABLE NAME!
Besides, you already have an internal name for it, so why assign it another name. You can just use playerlist inside the function.
Your code didn't work because you typed a key and immediately returned it. In order for the code to work, you must use the key to find the value. In this task, it is in the format of '' key1 ', value1,' key2 ', value2, ...]. In the function, index is a variable that stores the position of the key. And it finds the position of key through loop. It then returns list [index + 1] to return the value corresponding to the key.
playerlist = []
def find_player(playerlist):
list = playerlist
name = str(input("Search keyword: "))
index = 0
for s in list:
if name == str(s):
return ("This keyword's value: %d" % (list[index+1]))
index+=1
print (find_player(playerlist))
twilioCli = Client(accountSID, authToken)
message = twilioCli.messages.create(body="Your Shopping List:", from_ =twilioNum, to=myNum)
for keys,values in item_dict.items():
if keys == "" or values =="":
pass
else:
msg=twilioCli.messages.create(body='\n' + str(keys)+' '+ str(values) + '\n', from_=twilioNum, to=myNum)
how can i send sms in one msg vs multiples?
This is a very straight forward thing and I am confused. Please explain to me why twilio sends separate sms messages vs one?
program is simple, I have a grocery list, in the form of a dictionary and user checks items and enters a quantity. it iterates thru dictionary and should send checked items in the body of sms. But in my case i see multiple items. Thank you in advance
Twilio developer evangelist here.
You have one message being sent in the second line that just contains the string "Your Shopping List:".
To send as one message, I'd modify how you iterate through the key, value pairs in your dictionary so you move the for loop to the end like this:
for keys,values in item_dict.items():
if keys == "" or values =="":
pass
msg2Send = "Your Shopping List: \n" + \
('\n'.join(f'{key}: {value}' for key, value in item_dict.items()))
msg = twilioCli.messages.create(
body=msg2Send, from_="twilioNum", to="myNum")
Let me know if this helps at all!
I've scraped some websites and stored the html info in a sqlite database. Now, I want to extract and store the email addresses. I'm able to successfully extract and print the id and emails. But, I keep getting TypeError: "'NoneType' object is not subscriptable" and "sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type" when I try to update the database with these new email addresses.
I've verified that the data types I'm using in the update statement are the same as my database (id is class int and email is str). I've googled a bunch of different examples and mucked around with the syntax alot.
I also tried removing the Where Clause in the update statement but got the same errors.
import sqlite3
import re
conn = sqlite3.connect('spider.sqlite')
cur = conn.cursor()
x = cur.execute('SELECT id, html FROM Pages WHERE html is NOT NULL and email is NULL ORDER BY RANDOM()').fetchone()
#print(x)#for testing purposes
for row in x:
row = cur.fetchone()
id = row[0]
html = row[1]
email = re.findall(b'[a-z0-9\.\-+_]+#[a-z0-9\.\-+_]+\.[a-z]+', html)
#print(email)#testing purposes
if not email:
email = 'no email found'
print(id, email)
cur.execute('''UPDATE pages SET email = ? WHERE id = ? ''', (email, id))
conn.commit
I want the update statement to update the database with the extracted email addresses for the appropriate row.
There are a few things going on here.
First off, you don't want to do this:
for row in x:
row = cur.fetchone()
If you want to iterate over the results returned by the query, you should consider something like this:
for row in cur.fetchall():
id = row[0]
html = row[1]
# ...
To understand the rest of the errors you are seeing, let's take a look at them step by step.
TypeError: "'NoneType' object is not subscriptable":
This is likely generated here:
row = cur.fetchone()
id = row[0]
Cursor.fetchone returns None if the executed query doesn't match any rows or if there are no rows left in the result set. The next line, then, is trying to do None[0] which would raise the error in question.
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type:
re.findall returns a list of non-overlapping matches, not an individual match. There's no support for binding a Python list to a sqlite3 text column type. To fix this, you'll need to get the first element from the matched list (if it exists) and then pass that as your email parameter in the UPDATE.
.findall() returns a list.
You want to iterate over that list:
for email in re.findall(..., str(html)):
print(id, email)
cur.execute(...)
Not sure what's going on with that b'[a-z...' expression.
Recommend you use a raw string instead: r'[a-z...'.
It handles regex \ backwhacks nicely.
My bot passes a simple string (query.query) through a function that returns a "big" dictionary with many subdictionaries (each representing "card" data) inside it. As it works right now, all keys and values for all returned subdictionaries get displayed in-line (until pagination limit). So for example, writing "blue" will return the key:value pairs for all subdictionaries whose card name == "blue".
I want the bot to first display inline results for card names and, after the user chooses a card, for the bot to display the rest of the card data, so the user can choose what part to send in chat. This would look like:
User queries the word "blue" and makes card titles for "blue blob", "blue drake", "blue beard" appear in-line
User select "blue beard" from that menu, making bot then display available data for "blue-beard" in-line (stats, attack, etc.)
Here's a snippet of said code. Check the # comment to see where I think it all breaks down
#bot.inline_handler(lambda query: len(query.query) > 3)
def query_card(inline_query):
temp_names_list = []
results_list = []
try:
sound_dict = scrape(inline_query.query)
for key, sub_dict in sound_dict.items():
temp_names_list.append(types.InlineQueryResultArticle(id=key, title=sub_dict['Name'], input_message_content=types.InputTextMessageContent(sub_dict['Name'])))
bot.answer_inline_query(inline_query.id, temp_names_list, cache_time=1)
#The code breaks down here since I haven't found a way of passing the result to ^ this answer_inline_query into the next part of the loop:
for key, sub_dict in sound_dict.items():
for k, v in sub_dict.items():
if k == ['message']['text']:
results_list.append(types.InlineQueryResultArticle(id=key+k, title=k, input_message_content=types.InputTextMessageContent(sub_dict['Name']+"\'s ["+k+"] bit:\n"+v)))
#results_list.append(types.InlineQueryResultVoice(id=k, voice_url=v, title="^ "+sound_dict['Name']+"\'s ["+k+"] bit:\n"+v, caption=sound_dict['Name']+"\'s ["+k+"] bit"))
bot.answer_inline_query(inline_query.id, results_list, cache_time=1)
except Exception as e:
print(e)
I am retrieving information from a sqlite DB that gives me back around 20 million rows that I need to process. This information is then transformed into a dict of lists which I need to use. I am trying to use generators wherever possible.
Can someone please take a look at this code and suggest optimization please? I am either getting a “Killed” message or it takes a really long time to run. The SQL result set part is working fine. I tested the generator code in the Python interpreter and it doesn’t have any problems. I am guessing the problem is with the dict generation.
EDIT/UPDATE FOR CLARITY:
I have 20 million rows in my result set from my sqlite DB. Each row is of the form:
(2786972, 486255.0, 4125992.0, 'AACAGA', '2005’)
I now need to create a dict that is keyed with the fourth element ‘AACAGA’ of the row. The value that the dict will hold is the third element, but it has to hold the values for all the occurences in the result set. So, in our case here, ‘AACAGA’ will hold a list containing multiple values from the sql result set. The problem here is to find tandem repeats in a genome sequence. A tandem repeat is a genome read (‘AACAGA’) that is repeated atleast three times in succession. For me to calculate this, I need all the values in the third index as a list keyed by the genome read, in our case ‘AACAGA’. Once I have the list, I can subtract successive values in the list to see if there are three consecutive matches to the length of the read. This is what I aim to accomplish with the dictionary and lists as values.
#!/usr/bin/python3.3
import sqlite3 as sql
sequence_dict = {}
tandem_repeat = {}
def dict_generator(large_dict):
dkeys = large_dict.keys()
for k in dkeys:
yield(k, large_dict[k])
def create_result_generator():
conn = sql.connect('sequences_mt_test.sqlite', timeout=20)
c = conn.cursor()
try:
conn.row_factory = sql.Row
sql_string = "select * from sequence_info where kmer_length > 2"
c.execute(sql_string)
except sql.Error as error:
print("Error retrieving information from the database : ", error.args[0])
result_set = c.fetchall()
if result_set:
conn.close()
return(row for row in result_set)
def find_longest_tandem_repeat():
sortList = []
for entry in create_result_generator():
sequence_dict.setdefault(entry[3], []).append(entry[2])
for key,value in dict_generator(sequence_dict):
sortList = sorted(value)
for i in range (0, (len(sortList)-1)):
if((sortList[i+1]-sortList[i]) == (sortList[i+2]-sortList[i+1])
== (sortList[i+3]-sortList[i+2]) == (len(key))):
tandem_repeat[key] = True
break
print(max(k for k, v in tandem_repeat.items() if v))
if __name__ == "__main__":
find_longest_tandem_repeat()
I got some help with this on codereview as #hivert suggested. Thanks. This is much better solved in SQL rather than just code. I was new to SQL and hence could not write complex queries. Someone helped me out with that.
SELECT *
FROM sequence_info AS middle
JOIN sequence_info AS preceding
ON preceding.sequence_info = middle.sequence_info
AND preceding.sequence_offset = middle.sequence_offset -
length(middle.sequence_info)
JOIN sequence_info AS following
ON following.sequence_info = middle.sequence_info
AND following.sequence_offset = middle.sequence_offset +
length(middle.sequence_info)
WHERE middle.kmer_length > 2
ORDER BY length(middle.sequence_info) DESC, middle.sequence_info,
middle.sequence_offset;
Hope this helps someone with around the same idea. Here is a link to the thread on codereview.stackexchange.com