Queue runs successfully! Exits instead of continue, after Break - python

I am using this script to resolve thousands of domains. It runs successfully, and ends when the queue is empty. I am trying to it to break out of the loop and continue the script by printing.
How do I get this code to break out of the loop, ans print, when the queue is empty?
q = queue.Queue()
for name in names:
q.put(name)
def async_dns():
s = adns.init()
while True:
try:
dname = q.get(False)
q.task_done()
except queue.Empty:
return
response = s.synchronous(dname,adns.rr.NS)[0]
if response == 0:
dot_net.append("Y")
print(dname + ", is Y")
elif response == 300 or response == 30 or response == 60:
dot_net.append("N")
print(dname + ", is N")
threads = []
for i in range(20):
t = threading.Thread(target=async_dns)
threads.append(t)
t.start()
print("Done !!")

You could simply move the code that does the dns lookup and prints the result into the body of the try/except block:
def async_dns():
s = adns.init()
while True:
try:
dname = q.get(False)
response = s.synchronous(dname,adns.rr.NS)[0]
if response == 0:
dot_net.append("Y")
print(dname + ", is Y")
elif response == 300 or response == 30 or response == 60:
dot_net.append("N")
print(dname + ", is N")
q.task_done()
except queue.Empty:
return
Now when the queue is empty a queue.Empty will be raised and the exception handler will simply exit the thread function, otherwise it will print out the dns values.

Related

I want to run and kill a thread on a button press

I have a program that is supposed to send a few data points over a serial connection to an arduino which will control some motors to move. I can send the control signals individually as well as by txt file which will run repeatedly until the file is complete. While running a txt file, I want to be able to exit the loop like a pause or stop button. I think the best way to do that is via a thread that I can close. I have never done any threading before and my rudimentary attempts have not worked. Here is the function that sends the file data.
def send_file():
# Global vars
global moto1pos
global motor2pos
# Set Ready value
global isready
# Get File location
program_file_name = file_list.get('active')
file_path = "/home/evan/Documents/bar_text_files/"
program_file = Path(file_path + program_file_name)
file = open(program_file)
pos1 = []
pos2 = []
speed1 = []
speed2 = []
accel1 = []
accel2 = []
for each in file:
vals = each.split()
pos1.append(int(vals[0]))
pos2.append(int(vals[1]))
speed1.append(int(vals[2]))
speed2.append(int(vals[3]))
accel1.append(int(vals[4]))
accel2.append(int(vals[5]))
# Send file values
try:
while isready == 1:
for i in range(len(pos1)):
print("Step: " + str(i+1))
data = struct.pack("!llhhhh", pos1[i], pos2[i], speed1[i], speed2[i], accel1[i], accel2[i])
ser.write(data)
try:
pos1time = abs(pos1[i]/speed1[i])
except:
pos1time = 0
try:
pos2time = abs(pos2[i]/speed2[i])
except:
pos2time = 0
time_array = (pos1time, pos2time)
time.sleep(max(time_array))
motor1pos = ser.readline()
motor2pos = ser.readline()
if i < (len(pos1)-1):
isready = ord(ser.read(1))
else:
isready = 0
except:
print("Error: data not sent. Check serial port is open")
Here is the threading command which I want the sendfile command to work from.
def thread():
try:
global isready
isready = 1
t = threading.Thread(name='sending_data', target=command)
t.start()
except:
print("Threading Error: you don't know what you are doing")
And here is the stop function I want the thread to be killed by:
def stop():
try:
global isready
isready = 0
t.kill()
except:
print("Error: thread wasn't killed")
I know you aren't supposed to kill a thread but the data isn't very important. Whats more important is to stop the motors before something breaks.
The button in tkinter is:
run_file_butt = tk.Button(master = file_frame, text = "Run File", command = thread)
When I click the button, the program runs but the stop function does nothing to stop the motion.
Question: run and kill a thread on a button press
There is no such a thing called .kill(....
Start making your def send_file(... a Thread object which is waiting your commands.
Note: As it stands, your inner while isready == 1: will not stop by using m.set_state('stop').
It's mandatory to start the Thread object inside:
if __name__ == '__main__':
m = MotorControl()
import threading, time
class MotorControl(threading.Thread):
def __init__(self):
super().__init__()
self.state = {'is_alive'}
self.start()
def set_state(self, state):
if state == 'stop':
state = 'idle'
self.state.add(state)
def terminate(self):
self.state = {}
# main function in a Thread object
def run(self):
# Here goes your initalisation
# ...
while 'is_alive' in self.state:
if 'start' in self.state:
isready = 1
while isready == 1:
# Here goes your activity
# Simulate activity
print('running')
time.sleep(2)
isready = 0
self.state = self.state - {'start'}
self.state.add('idle')
elif 'idle' in self.state:
print('idle')
time.sleep(1)
if __name__ == '__main__':
m = MotorControl()
time.sleep(2)
m.set_state('start')
time.sleep(3)
m.set_state('stop')
time.sleep(3)
m.set_state('start')
time.sleep(4)
m.terminate()
print('EXIT __main__')
Your tk.Button should look like:
tk.Button(text = "Run File", command = lambda:m.set_state('start'))
tk.Button(text = "Stop File", command = lambda:m.set_state('stop'))
tk.Button(text = "Terminate", command = m.terminate)
The answer I have gone with is simple due to my simple understanding of threading and unique circumstances with which I am using the threading. Instead of terminating the thread in a way I was hoping, I added another conditional statement to the sending line of the send_file function.
while isready == 1:
for i in range(len(pos1)):
if motorstop == False:
print("Step: " + str(i+1))
#data = struct.pack('!llllhhhhhhhh', pos1[i], pos2[i], pos3[i], pos4[i], speed1[i], speed2[i], speed3[i], speed[4], accel1[i], accel2[i], accel3[i], accel4[i])
data = struct.pack("!llhhhh", pos1[i], pos2[i], speed1[i], speed2[i], accel1[i], accel2[i])
ser.write(data)
else:
isready = 0
break
and I have updated my stop() func to the following:
def stop():
try:
global motorstop
global t
motorstop = True
t.join()
except:
print("Error: thread wasn't killed")
I'm not exactly sure how it works but it is much simpler than what was mentioned by #stovefl.
With this code, since the function is mostly just sleeping, it can run but it won't send any new information and then will .join() after the next iteration.

Iterating and keeping track of count

I am trying to iterate through a bit of code with a delay and also keep count of the time it's run.
I believe I have to use a while loop and a sleep loop but I'm unsure as to how they'd look together.
def download_image():
while True:
try:
image = requests.get(newmeme).content
except requests.RequestError:
print("Retrying downloading")
time.sleep(2 * 60)
else:
break
with open('image.jpg', 'wb') as f:
f.write(image)
print("Download done.")
def upload_image(count):
while True:
try:
twitter_API.update_with_media("image.jpg", status="dankmeme #{}".format(count))
except tweepy.TweepError:
print("Retrying uploading")
time.sleep(2 * 60)
else:
break
print("Image #{} uploaded at {:%H:%M}".format(count, datetime.now()))
count = 0
while True:
download_image()
upload_image()
count = count+1
time.sleep(300)

How do I print once in a while loop but still have the while loop run?

Reddit Bot Question: I'm trying to see if any comment has the phrase "Hello There." in it and if it doesn't have "Hello There." in it, I want it to print "Nothing Found." once and wait until a comment is found. It works like a charm but instead of printing "Nothing Found." once and waiting for another comment, it prints "Nothing Found." repeatedly for an infinite amount of time until a comment comes. I've tried multiple options and ways from multiple forums but I can't seem to get this correct. Here is the code:
def run_bot():
while True:
for comment in r.subreddit("test").comments(limit=10):
comment_text = comment.body.lower()
isMatch = any(string in comment_text for string in words_match)
if comment.id not in cache and isMatch and comment.author != r.user.me():
comment.reply("[GENERAL KENOBI!](https://youtu.be/rEq1Z0bjdwc)\n\n^(*I am a bot, and this action was performed automatically.*)")
print(comment.id)
cache.append(comment.id)
with open("commentcache.txt", "a") as f:
f.write(comment.id + "\n")
print("Resetting in:")
def countdown(n):
while n > 0:
print (n, "...")
n = n - 1
time.sleep(1)
if n ==0:
print("Reset Successful!")
time.sleep(1)
countdown(5)
else:
print("Nothing Found.")
def saved():
if not os.path.isfile("commentcache.txt"):
commentcache = []
else:
with open("commentcache.txt", "r") as f:
commentcache = f.read
commentcache = commentcache().split("\n")
commentcache = list(filter(None, commentcache))
return commentcache
cache = saved()
print(cache)
run_bot()
The trouble starts at:
else:
print("Nothing Found.")
it prints that infinitely.
The easiest way is probably a boolean flag:
print_status = True
while True:
...
if isMatch and ...:
comment.reply("[GENERAL KENOBI!] ...")
...
print_status = True
elif print_status:
print("Nothing found")
print_status = False

Python script stuck at queue.join()

I am trying to implement a server for handling many clients (from thenewboston python reverse shell tutorials). I have the exact same code but when i run the script it gets stuck at queue.join(). How to make it work? I am unable to figure it out.
Here is the code
import socket
import sys
import threading
from queue import Queue
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
all_connections = []
all_addresses = []
# thread 1
# create socket (allows two computers to connect)
def socket_create():
try:
global host # ip address of the server
global port # port is to identify the kind of data
global s
host = ''
port = 9999
s = socket.socket()
except socket.error as msg:
print("Socket creation error: " + str(msg))
return
# bind socket to port and wait for connection from client
def socket_bind():
try:
global host
global port
global s
print("Binding socket to port: " + str(port))
s.bind((host, port))
s.listen(5)
# 5 is the no. of conections that can be made before server starts rejecting other requests
except socket.error as msg:
print("Socket binding error: " + str(msg) + "\n" + "Retrying...")
socket_bind()
return
# accept connections from multiple clients and save to list
def accept_connections():
for c in all_connections:
c.close()
del all_connections[:]
del all_addresses[:]
while 1:
try:
conn, address = s.accept()
conn.setblocking(1)
all_connections.append(conn)
all_addresses.append(address)
print("\nConnection has been establish: " + address[0])
except:
print("Error accepting connections")
return
# thread 2
# custom command promt for sending commands remotely
def start_turtle():
while True:
cmd = input('turtle> ')
if cmd == 'list':
list_connections()
elif 'select' in cmd:
conn = get_target(cmd)
if conn is not None:
send_target_commands(conn)
else:
print("Command not recognized")
return
# listing all the connections with indexing in the custom promt
def list_connections():
results = ''
for i, conn in enumerate(all_connections):
try:
conn.send(str.encode(' '))
conn.recv(20480)
except:
del all_connections[i]
del all_addresses[i]
continue
results += str(i) + ' ' + str(all_addresses[i][0]) + ' ' + str(all_addresses[i][1]) + '\n'
print('-----Clients-----' + '\n' + results)
return
# select a target client
def get_target(cmd):
try:
target = cmd.replace('select ', '')
target = int(target)
conn = all_connections[target]
print("You are now connected to " + str(all_addresses[target][0]))
print(str(all_addresses[target][0]) + '> ', end="")
return conn
except:
print("Not a valid selection")
return None
return
# connect with remote target client
def send_target_commands(conn):
while True:
try:
cmd = input()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
client_response = str(conn.recv(20480), "utf-8")
print(client_response, end="")
if cmd == "quit":
break
except:
print("Connection was lost")
break
return
# create worker threads
def create_workers():
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work)
t.daemon = True
t.start
return
# do the next job in the queue (one handles connections, other sends commands)
def work():
while True:
x = queue.get()
if x == 1:
socket_create()
socket_bind()
accept_connections()
if x == 2:
start_turtle()
queue.task_done()
return
# create jobs for later extracting them and assigning them to the threads
def create_jobs():
for x in JOB_NUMBER:
queue.put(x)
queue.join()
return
def main():
create_workers()
create_jobs()
if __name__ == '__main__':
main()
Since you are using infinite loops (while True) at start_turtle and (while 1) at accept_connections they are not returning.
Since they don't return the func work never calls queue.task_done(), so the queue stuck joining.
I'm afraid you need to do one of the following:
start both start_turtle and accept_connections in parallel processes or threads.
Be sure they should call the queue.task_done().
For instance, you may include the queue as parameter and call it before starting the infinite loops (second option).
def work():
while True:
x = queue.get()
if x == 1:
socket_create()
socket_bind()
accept_connections(queue) # call queue.task_done() there
if x == 2:
start_turtle(queue) # call queue.task_done() in start_turtle
return
def start_turtle(queue):
queue.task_done() # Join one item from the queue
while True:
cmd = input('turtle> ')
if cmd == 'list':
list_connections()
elif 'select' in cmd:
conn = get_target(cmd)
if conn is not None:
send_target_commands(conn)
else:
print("Command not recognized")
return
On the other hand, in your create_workers you don't call the start method of the thread so your workers didn't really start.
Perhaps this is a typo.
def create_workers():
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work)
t.daemon = True
# t.start # Not starting the Thread
t.start() # You need to call the start method
return

Repeat an iteration in loop if error occurs

Is there a command such as break and continue which could repeat recent iteration?
For example, when exception is thrown.
for i in range(0,500):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except:
repeat
Let's have an iteration where i variable's value is 6. During this iteration some connection error occurred. I want to repeat this iteration.
Is there a command which can do that?
Of course I can do this:
i=0
while i!=500:
try:
conn = getConnection(url+str(i))
doSomething(conn)
i+=1
except:
pass
No, there is no command to "rewind" a for-loop in Python.
You could use a while True: loop inside the for-loop:
for i in range(500):
while True:
try:
conn = getConnection(url+str(i))
doSomething(conn)
except Exception: # Replace Exception with something more specific.
continue
else:
break
or without the else::
for i in range(500):
while True:
try:
conn = getConnection(url+str(i))
doSomething(conn)
break
except Exception: # Replace Exception with something more specific.
continue
But I personally think that your proposed solution is better because it avoids an indentation level.
for i in range(500):
while True
try:
conn = getConnection(url+str(i))
break
except Exception: # still allows to quit with KeyboardInterrupt
continue
do_your_stuff()
This looks bit risky, however, you should at least enable some logging inside a while block.
If you expect to use it in more places, you might write a simple decorator:
def keep_trying(fn, *args, **kwargs):
def inner(*args, **kwargs):
while True:
try:
return fn(*args, **kwargs)
except Exception:
continue
return inner
# later you can use it simple like this:
for i in range(500):
conn = keep_trying(getConnection)(url+str(i))
You can use generators :
def process_connections(n_connections, url, max_tries=50):
i = 0
try_count = 0
while i < n_connections:
try:
conn = getConnection(url+str(i))
yield conn
except:
try_count += 1
if try_count > max_tries:
raise Exception("Unable to connect after %s tries" % max_tries)
else:
i += 1 # increments only if no exception
And you perform your operations :
for conn in process_connections(500, url):
do_something(conn)
You can use nested for loops to put a cap on the number of times you retry the operation. This is bascially the sam as #PierreAlex's generator answer but without the extra function definition.
for i in range(500):
for retry in range(10):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except Exception: # Replace Exception with something more specific.
time.sleep(1)
else:
print "iteration", i, "failed"
Why not just use an if statement?
n=6
i=0
while i!=500:
failed = False;
try:
conn = getConnection(url+str(i))
doSomething(conn)
i+=1
except:
#handle error
failed = True;
#try again if n-th case failed first time
if(i == n and failed):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except:
#handle error
Here is one. You would need to add a logging or alert system to let you know that something is stuck:
state = "" #state of the loop
# If there is no error continue. If there is error, remain in loop
while True:
if state != "error":
try:
1/0 # command
break # no error so break out of loop
except:
state = "error" #declare error so maintain loop
continue
elif state == "error": # maintain loop
continue

Categories