Threading object issue - python

I can't figure out why the threading object threadObj can't use isAlive, when I call stop(). The code is described below.
from threading import Thread
class workerThread(Thread):
def __init__(self, _parent):
Thread.__init__(self)
self.parent = _parent
self.active = False
def run(self):
while(self.active == False):
print 'I am here'
print 'and now I am here'
class imp():
def __init__(self):
self.threadObj = None
def start(self):
self.threadObj = workerThread(self)
self.threadObj.start()
def stop(self):
if self.threadObj.isAlive() == True:
print 'it is alive'
It says: AttributeError: 'NoneType' object has no attribute 'isAlive'
The calling code is descibed below:
from filename import imp
filename = imp()
if option == 'A':
filename.start()
elif option == 'B':
filename.stop()

Your issue appears to be that you mistakenly believe that your Threads are persistent between invocations of your program, which is not correct. When you call python callingCode.py A, your program runs and executes the if option == 'A' block of code. Then it exits, and your thread is cleaned up. The second time, when you call python callingCode.py B, the thread is never created.

Based on what you've posted:
from filename import imp
filename = imp() # you create an object here
if option == 'A':
# if option is B, you are not launching the Thread
# another words, this start() method will not be executed
filename.start()
elif option == 'B':
# At this moment threadObj is None
# because it wasn't started
filename.stop()
I would suggest you to use ptd to find this type of bugs:
from filename import imp
filename = imp()
import ptb
ptb.set_trace()
if option == 'A':
filename.start()
elif option == 'B':
filename.stop()

Related

Python multiprocessing exits without exception when accessing shared value. Is this normal?

I am trying to share a string between processes with multiprocessing.Value(c_wchar_p, ""). Program exits unexpectedly without exception with code (0xC0000005). I am guessing that problem is somehow caused by main process trying to access memory of child process. Issue occurs only when ctypes c_char_p/c_wchar_p are used. Thread works fine. Is this expected beheavor?
Steps to reproduce:
import multiprocessing
import threading
import ctypes
import time
class ProcessExample:
def __init__(self, proc: bool):
self.shared_bool = multiprocessing.Value(ctypes.c_bool, False)
self.shared_string = multiprocessing.Value(ctypes.c_wchar_p, "one")
self.shared_byte = multiprocessing.Value(ctypes.c_char_p, b"one")
if proc:
self.th_proc = multiprocessing.Process(target=self.target, args=(self.shared_bool, self.shared_string, self.shared_byte))
else:
self.th_proc = threading.Thread(target=self.target, args=(self.shared_bool, self.shared_string, self.shared_byte))
self.th_proc.start()
#staticmethod
def target(shared_bool, shared_string, shared_byte):
shared_bool.value = True
shared_string.value = "two"
shared_byte.value = b"two"
def print_values(self):
self.th_proc.join()
print(self.shared_bool.value)
print(self.shared_string.value) # Exits
print(self.shared_byte.value) # Exits
if __name__ == "__main__":
# example = ProcessExample(False) # Works
example = ProcessExample(True)
time.sleep(1)
example.print_values()
Output
True
Process finished with exit code -1073741819 (0xC0000005)
I think the problem is in multiprocessing.Value(ctypes.c_wchar_p, "one") and multiprocessing.Value(ctypes.c_char_p, b"one"). To have string/byte string initialized correctly, use multiprocessing.Array:
import multiprocessing
import threading
import ctypes
import time
class ProcessExample:
def __init__(self, proc: bool):
self.shared_bool = multiprocessing.Value(ctypes.c_bool, False)
self.shared_string = multiprocessing.Array(ctypes.c_wchar, "one")
self.shared_byte = multiprocessing.Array(ctypes.c_char, b"one")
if proc:
self.th_proc = multiprocessing.Process(
target=self.target,
args=(self.shared_bool, self.shared_string, self.shared_byte),
)
else:
self.th_proc = threading.Thread(
target=self.target,
args=(self.shared_bool, self.shared_string, self.shared_byte),
)
self.th_proc.start()
#staticmethod
def target(shared_bool, shared_string, shared_byte):
shared_bool.value = True
shared_string[:] = "two"
shared_byte[:] = b"two"
def print_values(self):
self.th_proc.join()
print(self.shared_bool.value)
print(self.shared_string[:])
print(self.shared_byte[:])
if __name__ == "__main__":
example = ProcessExample(True)
time.sleep(1)
example.print_values()
Prints:
True
two
b'two'

Is it safe in Python to assign a new value to variable from one thread while it is read from the another thread?

I have a short script (below) where one thread is continuously checking the state of variable (if it is None or not). Is this approach safe without using a Lock, or is there any possibility that the checking thread could read "something strange between None and the reference on the new value"?
Thank you for answer, Martin
import time
import threading
class A(object):
def __init__(self):
self.data = None
self.e = threading.Event()
self.e.set()
self.checking_thread = threading.Thread(target=self.__check_if_not_none)
self.checking_thread.start()
def __check_if_not_none(self):
while self.e.is_set():
if self.data is not None:
print("Ready")
else:
print("None")
def prepare_data(self):
data = []
data.extend([1, 2, 3, 4, 5]) # Data preparing...
self.data = data
def quit(self):
self.e.clear()
self.checking_thread.join()
print("Done")
if __name__ == "__main__":
a = A()
time.sleep(0.001)
a.prepare_data()
time.sleep(0.001)
a.quit()

Stop a python thread from destructor

I am somewhat new to Python programming. I am trying to make a script which will continously read a USB device in a separate thread (as this class will be imported into some GUI apps) using a dll, If there are any data it will call the callback function.
My problem is I want to stop the thread using the destructor and I am not sure about other better design to do it? Could any body please point me out if there are better methods?
My design is planned where my class can be imported and then, call the run through start, once the last object is destroyed the thread stops.
# -*- coding: utf-8 -*-
import ctypes
import threading
import time
USB_VENDOR_ID = 0x23ef
USB_PRODUCT_ID = 0x0001
class usb_dev_comm(threading.Thread):
def __init__(self, callback_fun):
self.hidDll = ctypes.WinDLL("AtUsbHid.dll")
self.usb_dev_connected = 0
self.usb_stopall = 0
self.callback = callback_fun
return
def usb_dev_present(self):
self.res = self.hidDll.findHidDevice(USB_VENDOR_ID, USB_PRODUCT_ID)
if (self.res == True):
self.usb_dev_connected = 1
else:
self.usb_dev_connected = 0
return self.res
def usb_dev_tx(self,data):
self.res = self.hidDll.writeData(data)
return self.res
def usb_dev_rx(self):
data = 0
result = self.hidDll.readData(data)
if (result == False):
return False
else:
return data
def run(self):
while 1:
self.usb_dev_present()
print self.usb_dev_connected
if(self.usb_dev_connected):
data_rx = self.usb_dev_rx()
print data_rx
#time.sleep(0.001)
time.sleep(1)
def __del__(self):
print "del:cleanup required"
#TODO
if __name__ == "__main__":
def data_print(data):
print data
device = usb_dev_comm(data_print)
result = device.run()
print result
print device.usb_dev_connected
I tried introducing
def run(self):
while self.stop_thread:
self.usb_dev_present()
print self.usb_dev_connected
if(self.usb_dev_connected):
data_rx = self.usb_dev_rx()
print data_rx
#time.sleep(0.001)
time.sleep(1)
def __del__(self):
self.stop_thread = 1
print "del:cleanup required"
#TODO
But this is not working as I think this leads to chicken and egg problem

Multithreading (?): Manual interference in a loop

I've been looking into a way to directly change variables in a running module.
What I want to achieve is that a load test is being run and that I can manually adjust the call pace or whatsoever.
Below some code that I just created (not-tested e.d.), just to give you an idea.
class A():
def __init__(self):
self.value = 1
def runForever(self):
while(1):
print self.value
def setValue(self, value):
self.value = value
if __name__ == '__main__':
#Some code to create the A object and directly apply the value from an human's input
a = A()
#Some parallelism or something has to be applied.
a.runForever()
a.setValue(raw_input("New value: "))
Edit #1: Yes, I know that now I will never hit the a.setValue() :-)
Here is a multi-threaded example. This code will work with the python interpreter but not with the Python Shell of IDLE, because the raw_input function is not handled the same way.
from threading import Thread
from time import sleep
class A(Thread):
def __init__(self):
Thread.__init__(self)
self.value = 1
self.stop_flag = False
def run(self):
while not self.stop_flag:
sleep(1)
print(self.value)
def set_value(self, value):
self.value = value
def stop(self):
self.stop_flag = True
if __name__ == '__main__':
a = A()
a.start()
try:
while 1:
r = raw_input()
a.set_value(int(r))
except:
a.stop()
The pseudo code you wrote is quite similar to the way Threading / Multiprocessing works in python. You will want to start a (for example) thread that "runs forever" and then instead of modifying the internal rate value directly, you will probably just send a message through a Queue that gives the new value.
Check out this question.
Here is a demonstration of doing what you asked about. I prefer to use Queues to directly making calls on threads / processes.
import Queue # !!warning. if you use multiprocessing, use multiprocessing.Queue
import threading
import time
def main():
q = Queue.Queue()
tester = Tester(q)
tester.start()
while True:
user_input = raw_input("New period in seconds or (q)uit: ")
if user_input.lower() == 'q':
break
try:
new_speed = float(user_input)
except ValueError:
new_speed = None # ignore junk
if new_speed is not None:
q.put(new_speed)
q.put(Tester.STOP_TOKEN)
class Tester(threading.Thread):
STOP_TOKEN = '<<stop>>'
def __init__(self, q):
threading.Thread.__init__(self)
self.q = q
self.speed = 1
def run(self):
while True:
# get from the queue
try:
item = self.q.get(block=False) # don't hang
except Queue.Empty:
item = None # do nothing
if item:
# stop when requested
if item == self.STOP_TOKEN:
break # stop this thread loop
# otherwise check for a new speed
try:
self.speed = float(item)
except ValueError:
pass # whatever you like with unknown input
# do your thing
self.main_code()
def main_code(self):
time.sleep(self.speed) # or whatever you want to do
if __name__ == '__main__':
main()

Trigger an event when clipboard content changes

I'm trying to get the clipboard content using a Python script on my Mac Lion.
I'm searching for an event or something similar, because if I use a loop, my application spends all its time watching the clipboard.
Any ideas?
Have you thought about using an endless loop and "sleeping" between tries?
I used pyperclip for a simple PoC and it worked like a charm, and Windows and Linux.
import time
import sys
import os
import pyperclip
recent_value = ""
while True:
tmp_value = pyperclip.paste()
if tmp_value != recent_value:
recent_value = tmp_value
print("Value changed: %s" % str(recent_value)[:20])
time.sleep(0.1)
Instead of the print, do whatever you want.
Here is a complete multithreading example.
import time
import threading
import pyperclip
def is_url_but_not_bitly(url):
if url.startswith("http://") and not "bit.ly" in url:
return True
return False
def print_to_stdout(clipboard_content):
print ("Found url: %s" % str(clipboard_content))
class ClipboardWatcher(threading.Thread):
def __init__(self, predicate, callback, pause=5.):
super(ClipboardWatcher, self).__init__()
self._predicate = predicate
self._callback = callback
self._pause = pause
self._stopping = False
def run(self):
recent_value = ""
while not self._stopping:
tmp_value = pyperclip.paste()
if tmp_value != recent_value:
recent_value = tmp_value
if self._predicate(recent_value):
self._callback(recent_value)
time.sleep(self._pause)
def stop(self):
self._stopping = True
def main():
watcher = ClipboardWatcher(is_url_but_not_bitly,
print_to_stdout,
5.)
watcher.start()
while True:
try:
print("Waiting for changed clipboard...")
time.sleep(10)
except KeyboardInterrupt:
watcher.stop()
break
if __name__ == "__main__":
main()
I create a subclass of threading.Thread, override the methods run and __init__ and create an instance of this class. By calling watcher.start() (not run()!), you start the thread.
To safely stop the thread, I wait for <Ctrl>-C (keyboard interrupt) and tell the thread to stop itself.
In the initialization of the class, you also have a parameter pause to control how long to wait between tries.
Use the class ClipboardWatcher like in my example, replace the callback with what you do, e.g., lambda x: bitly(x, username, password).
Looking at pyperclip the meat of it on Macosx is :
import os
def macSetClipboard(text):
outf = os.popen('pbcopy', 'w')
outf.write(text)
outf.close()
def macGetClipboard():
outf = os.popen('pbpaste', 'r')
content = outf.read()
outf.close()
return content
These work for me how do you get on?
I don't quite follow your comment on being in a loop.
EDIT Added 'orrid polling example that shows how changeCount() bumps up on each copy to the pasteboard. It's still not what the OP wants as there seems no event or notification for modifications to the NSPasteboard.
from LaunchServices import *
from AppKit import *
import os
from threading import Timer
def poll_clipboard():
pasteboard = NSPasteboard.generalPasteboard()
print pasteboard.changeCount()
def main():
while True:
t = Timer(1, poll_clipboard)
t.start()
t.join()
if __name__ == "__main__":
main()
simple!
import os
def macSetClipboard(text):
outf = os.popen('pbcopy', 'w')
outf.write(text)
outf.close()
def macGetClipboard():
outf = os.popen('pbpaste', 'r')
content = outf.read()
outf.close()
return content
current_clipboard = macGetClipboard()
while True:
clipboard = macGetClipboard()
if clipboard != current_clipboard:
print(clipboard)
macSetClipboard("my new string")
print(macGetClipboard())
break
I originaly posted my answer on a duplicate Run a python code when copying text with specific keyword
Here the answer I came up with.
import clipboard
import asyncio
# Exemple function.
async def your_function():
print("Running...")
async def wait4update(value):
while True:
if clipboard.paste() != value : # If the clipboard changed.
return
async def main():
value = clipboard.paste() # Set the default value.
while True :
update = asyncio.create_task(wait4update(value))
await update
value = clipboard.paste() # Change the value.
asyncio.create_task(your_function()) #Start your function.
asyncio.run(main())

Categories

Resources