If statement not returning the desired result - mysql

I'm new to Python and I believe the issue with my code is being caused by the fact that I'm a newbie and there's some theory or something that I must not be familiar with yet.
Yes, this question was asked before but, is different from mine. Believe me I tried everything that I thought that needs to be done.
Everything worked until I added everything in "if five in silos" statement.
After I enter the values for the 6 input functions, the program just finishes with exit code 0. Nothing else happens. The for loop is not initiated.
I want for the code to accept either 103 or 106 when prompting to enter something for the "five" variable.
I'm using PyCharm and Python 3.7.
import mysql.connector
try:
db = mysql.connector.connect(
host="",
user="",
passwd="",
database=""
)
one = int(input("Number of requested telephone numbers: "))
two = input("Enter the prefix (4 characters) with a leading 0: ")[:4]
three = int(input("Enter the ccid: "))
four = int(input("Enter the cid: "))
six = input("Enter case number: ")
five = int(input("Enter silo (103, 106 only): "))
cursor = db.cursor()
cursor.execute(f"SELECT * FROM n1 WHERE ddi LIKE '{two}%' AND silo = 1 AND ccid = 0 LIMIT {one}")
cursor.fetchall()
silos = (103, 106)
if five in silos:
if cursor.rowcount > 0:
for row in cursor:
seven = input(f"{row[1]} has been found on our system. Do you want to continue? Type either Y or N.")
if seven == "Y":
cursor.execute(f"INSERT INTO n{five} (ddi, silo, ccid, campaign, assigned, allocated, "
f"internal_notes, client_notes, agentid, carrier, alias) VALUES "
f"('{row[1]}', 1, {three}, {four}, NOW(), NOW(), 'This is a test.', '', 0, "
f"'{row[13]}', '') "
f"ON DUPLICATE KEY UPDATE "
f"silo = VALUES (silo), "
f"ccid = VALUES (ccid), "
f"campaign = VALUES (campaign);")
cursor.execute(f"UPDATE n1 SET silo = {five}, internal_notes = '{six}', allocated = NOW() WHERE "
f"ddi = '{row[1]}'")
else:
print("The operation has been canceled.")
db.commit()
else:
print(f"No results for prefix {two}.")
else:
print("Enter either silo 103 or 106.")
cursor.close()
db.close()
except (ValueError, NameError):
print("Please, enter an integer for all questions, except case number.")

Because it must be:
for row in cursor.fetchall():
// do something
In your code cursor returns a Python Class defined by db.cursor() but you need to call the fetchall() function to read the rows contained in it.
You're actually calling cursor.fetchall() without doing nothing with it, you can assign the call to a variable and than do this:
result = cursor.fetchall()
for row in result:
//do something

I found the problem: I had to store cursor.fetchall() into a variable.
After I put: eight = cursor.fetchall() before the "silos" tuple, everything worked perfectly.

Related

Python- Return a verified variable from a function to the main program

Can anyone please direct me to an example of where one can send a user input variable to a checking function or module & return the validated input assigning / updating the initialised variable?. I am trying to re-create something I did in C++ many years ago where I am trying to validate an integer! In this particular case that the number of bolts input in a building frame connection is such. Any direction would be greatly appreciated as my internet searches and trawls through my copy of Python A Crash Course have yet to shed any light! Many thanks in anticipation that someone will feel benevolent towards a Python newbie!
Regards Steve
Below is one on my numerous attempts at this, really I would just like to abandon and use While and a function call. In this one apparently I am not allowed to put > (line 4) between str and int, this desite my attempt to force N to be int - penultimate line!
def int_val(N):
#checks
# check 1. n > 0 for real entries
N > 0
isinstance(N, int)
N=N
return N
print("N not ok enter again")
#N = input("Input N the Number of bolts ")
# Initialiase N=0
#N = 0
# Enter the number of bolts
N = input("Input N the Number of bolts ")
int_val(N)
print("no of bolts is", N)
Is something like this what you have in mind? It takes advantage of the fact that using the built-in int function will convert a string to an integer if possible, but otherwise throw a ValueError.
def str_to_posint(s):
"""Return value if converted and greater than zero else None."""
try:
num = int(s)
return num if num > 0 else None
except ValueError:
return None
while True:
s = input("Enter number of bolts: ")
if num_bolts := str_to_posint(s):
break
print(f"Sorry, \"{s}\" is not a valid number of bolts.")
print(f"{num_bolts = }")
Output:
Enter number of bolts: twenty
Sorry, "twenty" is not a valid number of bolts.
Enter number of bolts: 20
num_bolts = 20
def str_to_posint(s):
"""Return value if converted and greater than zero else None."""
try:
num = int(s)
return num if num > 0 else None
except ValueError:
return None
while True:
s = input("Enter number of bolts: ")
if num_bolts := str_to_posint(s):
break
print(f"Sorry, "{s}" is not a valid number of bolts.")
print(f"{num_bolts = }")

Collecting Tweets using max_id is not working as expected

Iam currently doing a tweet search using Twitter Api. However, taking the tweet id is not working for me.
Here is my code:
searchQuery = '#BLM' # this is what we're searching for
searchQuery = searchQuery + "-filter:retweets"
Geocode="39.8, -95.583068847656, 2500km"
maxTweets = 1000000 # Some arbitrary large number
tweetsPerQry = 100 # this is the max the API permits
fName = 'tweetsBLM.json' # We'll store the tweets in a json file.
sinceId = None
#max_id = -1 # initial search
max_id=1278836959926980609 # the last id of previous search
tweetCount = 0
print("Downloading max {0} tweets".format(maxTweets))
with open(fName, 'w') as f:
while tweetCount < maxTweets:
try:
if (max_id <= 0):
if (not sinceId):
new_tweets = api.search(q=searchQuery,lang="en", geocode=Geocode,
count=tweetsPerQry)
else:
new_tweets = api.search(q=searchQuery,lang="en",geocode=Geocode,
count=tweetsPerQry,
since_id=sinceId )
else:
if (not sinceId):
new_tweets = api.search(q=searchQuery, lang="en", geocode=Geocode,
count=tweetsPerQry,
max_id=str(max_id - 1) )
else:
new_tweets = api.search(q=searchQuery, lang="en", geocode=Geocode,
count=tweetsPerQry,
max_id=str(max_id - 1),
since_id=sinceId)
if not new_tweets:
print("No more tweets found")
break
for tweet in new_tweets:
f.write(jsonpickle.encode(tweet._json, unpicklable=False) +
'\n')
tweetCount += len(new_tweets)
print("Downloaded {0} tweets".format(tweetCount))
max_id = new_tweets[-1].id
except tweepy.TweepError as e:
# Just exit if any error
print("some error : " + str(e))
print('exception raised, waiting 15 minutes')
print('(until:', dt.datetime.now() + dt.timedelta(minutes=15), ')')
time.sleep(15*60)
break
print ("Downloaded {0} tweets, Saved to {1}".format(tweetCount, fName))
This code works perfectly fine. I initially run it and got about 40 000 tweets. Then i took the id of the last tweet of previous/initial search to go back in time. However, i was disappointed to see that there were no tweets anymore. I can not believe that for a second. I must be going wrong somewhere because #BLM has been very active in the last 2/3 months.
Any help is very welcome. Thank you
I may have found the answer. Using Twitter API, it is not possible to get older tweets (7 days old or more). Using max_id to get around this is not possible either.
The only way is to stream and wait for more than 7 days.
Finally, there is also this link that look for older tweets
https://pypi.org/project/GetOldTweets3/ it is an extension of the original Jefferson Henrique's work

Updating one table of MYSQL with multiple processes via pymysql

Actually, I am trying to update one table with multiple processes via pymysql, and each process reads a CSV file split from a huge one in order to promote the speed. But I get the Lock wait timeout exceeded; try restarting transaction exception when I run the script. After searching the posts on this site, I found one post which mentioned that to set or build the built-in LOAD_DATA_INFILE, but no details on it. How can I do it with 'pymysql' to reach my aim?
---------------------------first edit----------------------------------------
Here's the job method:
`def importprogram(path, name):
begin = time.time()
print('begin to import program' + name + ' info.')
# "c:\\sometest.csv"
file = open(path, mode='rb')
csvfile = csv.reader(codecs.iterdecode(file, 'utf-8'))
connection = None
try:
connection = pymysql.connect(host='a host', user='someuser', password='somepsd', db='mydb',
cursorclass=pymysql.cursors.DictCursor)
count = 1
with connection.cursor() as cursor:
sql = '''update sometable set Acolumn='{guid}' where someid='{pid}';'''
next(csvfile, None)
for line in csvfile:
try:
count = count + 1
if ''.join(line).strip():
command = sql.format(guid=line[2], pid=line[1])
cursor.execute(command)
if count % 1000 == 0:
print('program' + name + ' cursor execute', count)
except csv.Error:
print('program csv.Error:', count)
continue
except IndexError:
print('program IndexError:', count)
continue
except StopIteration:
break
except Exception as e:
print('program' + name, str(e))
finally:
connection.commit()
connection.close()
file.close()
print('program' + name + ' info done.time cost:', time.time()-begin)`
And the multi-processing method:
import multiprocessing as mp
def multiproccess():
pool = mp.Pool(3)
results = []
paths = ['C:\\testfile01.csv', 'C:\\testfile02.csv', 'C:\\testfile03.csv']
name = 1
for path in paths:
results.append(pool.apply_async(importprogram, args=(path, str(name))))
name = name + 1
print(result.get() for result in results)
pool.close()
pool.join()
And the main method:
if __name__ == '__main__':
multiproccess()
I am new to Python. How can I make the code or the way itself goes wrong? Should I use only one single process to finish the data reading and importing?
Your issue is that you are exceeding the time allowed for a response to be fetched from the server, so the client is automatically timing out.
In my experience, adjust the wait timeout to something like 6000 seconds, combine into one CSV and just leave the data to import. Also, I would recommend running the query direct from MySQL rather than Python.
The way I usually import CSV data from Python to MySQL is through the INSERT ... VALUES ... method, and I only do so when some kind of manipulation of the data is required (i.e. inserting different rows into different tables).
I like your approach and understand your thinking but in reality there is no need. The benefit to the INSERT ... VALUES ... method is that you won't run into any timeout issue.

How to give a mysql record a timeout to expire after 30 minutes?

I was not able to find something relevant anywhere.
I would like to put a timeout on "password" that I am saving on mysql with python.
cur.execute("INSERT INTO generatedcode(password, codetimeout) VALUES (%s,
%s)", [passwordd, timestamp])
As I'm not sufficiently acquainted with python and hence I'll leave the specifics of the code to you; I will only present the idea of the solution and the relevant SQL commands (syntax will need to be verified as I don't have an environment to test it).
Let say that you want to set a timeout of 1 hour from the moment you save the password and your table has (at least) the following two fields: Password and Expiration (I assume that Password would be of binary type to allow encryption and Expiration would be of DATETIME type).
Then, you would implement the following SQL command:
INSERT INTO <your table> (Password , Expiration )
VALUES (%s , DATEADD(NOW(),3600))
[spaces added just for clarity purposes]
and send that string towards the DB where %s would be replaced by the value of the password.
What DATEADD(NOW(),3600) does is:
Gets the current date and time,
Adds one hour to it.
Once you have that inserted into your table, you would later on retrieve the password using the following command:
SELECT Password
FROM <your table>
WHERE User = <could be Username or any other key that you are using now>
AND Expiration > NOW()
meaning, get the password (if any) that its expiration datetime is still in the future.
Hope this is what you were looking for.
Cheers!!
EDIT:
I'm adding hereinafter your code after fixes:
#app.route('/signattendance', methods=['GET'])
def signattendance():
stamp = "signed"
error = None
# now = datetime.datetime.today()
# tdelta = datetime.timedelta(seconds=10000)
now = datetime.datetime.now()
if request.method == 'GET':
cur1 = mysql.connection.cursor()
result = cur1.execute("SELECT password FROM generatedcode WHERE codetimeout > NOW()")
if result is False:
cur = mysql.connection.cursor()
cur.execute("INSERT INTO attendance(studentattendance) VALUES(%s,DATEADD(NOW(),3600)", [stamp])
mysql.connection.commit()
cur.close()
# cur1.close()
flash('Succsefully signed', 'Acepted')
else:
flash('You couldnt sign attendance', 'Denied')
else:
return redirect(url_for('dashboard'))
return render_template('signattendance.html', error=error)
Note that I leave for the DB to check the current time.
if request.method == 'GET' or 'POST':
cur1 = mysql.connection.cursor()
result = cur1.execute("SELECT password FROM generatedcode "
"WHERE DATE_SUB(CURRENT_TIME (),INTERVAL 10 MINUTE) <= codetimeout;")

Python how to define a function that only accepts an integer input that can be used for multiple lines

I am trying to make a program that has a user input numbers into multiple different lines of code and I am trying to make it so that if the user inputs something other than a number the program will ask the user again to input the number correctly. I was trying to define a function that I could use for all of them but every time I run the program, it crashes. Any help would be much appreciated, thank you.
My code:
def error():
global m1
global m2
global w1
global w2
while True:
try:
int(m1 or m2 or w1 or w2)
except ValueError:
try:
float(m1 or m2 or w1 or w2)
except ValueError:
m1 or m2 or w1 or w2=input("please input your response correctly...")
break
m1=input("\nWhat was your first marking period percentage?")
error()
w1=input("\nWhat is the weighting of the first marking period? (in decimal)")
error()
m2=input("\nWhat was your second marking period percentage?")
error()
w2=input("\nWhat is the weighting of the second marking period? (in decimal)")
error()
def user_input(msg):
inp = input(msg)
try:
return int(inp) if inp.isnumeric() else float(inp)
except ValueError as e:
return user_input("Please enter a numeric value")
m1=user_input("\nWhat was your first marking period percentage?")
w1=user_input("\nWhat is the weighting of the first marking period? (in decimal)")
m2=user_input("\nWhat was your second marking period percentage?")
w2=user_input("\nWhat is the weighting of the second marking period? (in decimal)")
You should write your function to get one number at a time. If at exception is triggered somewhere, it should be handled. Note how the get_number function shown below will keep asking for a number but also shows the prompt specified by its caller. If you are not running Python 3.6 or higher, you will need to comment out the call to print in the main function.
#! /usr/bin/env python3
def main():
p1 = get_number('What is your 1st marking period percentage? ')
w1 = get_number('What is the weighting of the 1st marking period? ')
p2 = get_number('What is your 2nd marking period percentage? ')
w2 = get_number('What is the weighting of the 2nd marking period? ')
score = calculate_score((p1, p2), (w1, w2))
print(f'Your score is {score:.2f}%.')
def get_number(prompt):
while True:
try:
text = input(prompt)
except EOFError:
raise SystemExit()
else:
try:
number = float(text)
except ValueError:
print('Please enter a number.')
else:
break
return number
def calculate_score(percentages, weights):
if len(percentages) != len(weights):
raise ValueError('percentages and weights must have same length')
return sum(p * w for p, w in zip(percentages, weights)) / sum(weights)
if __name__ == '__main__':
main()
By the following code you can able to make a function that only accept integer value:
def input_type(a):
if(type(10)==type(a)):
print("integer")
else:
print("not integer")
a=int(input())
input_type(a)