I'm a huge fan of the Actor Model . I think that for most applications, it's the best way to do concurrency. As CPUs get more cores, concurrency becomes more important for programmers, and I think the Actor Model will become more important, too.
But, sometimes you need something more light-weight for handling "events". For example, imagine you have some code listening for file changes in a particular directory. What you'd like to do is make an "event" that is "fired" whenever a file change is detected. When fired, there may be a "handler" or "listener" which is notified of the event. That "handler" is ultimately just some code which is executed when the event occurs.
A while ago, I wanted an event system like this for Python. I didn't see anything builtin or any library available, so I decided to write my own. I'd like to share what I created with you.
But first, I want to follow an example through other programming languages to give you an idea of what I was trying to accomplish and how it compares with what's out there. After that, I'll give you my implemenation in Python. Our example will be listening for changes on the file system. We want to keep the "watcher" code decoupled from the rest of the code, so we use events.
The best implementation of events that I've used is in C#, so we'll start there. In C# 1.0, our file watcher would looks something like this:
public delegate void FileChangeHandler(string source_path); class FileWatcher { public event FileChangeHandler FileChanged; public void WatchForChanges() { ... if(FileChanged != null) { FileChanged(source_path); } ... } } class FileChangeLogger { public void OnFileChanged(string source_path) { Console.WriteLine(String.Format("{0} changed.", source_path)); } } watcher = FileWatcher(); logger = FileChangeLogger(); watcher.FileChanged += new FileChangeHandler(logger.OnFileChanged); watcher.WatchForChanges();It's pretty nice. The best part is at the end, where you can write "watcher.FileChange += ...". But, you need to type the completely useless "new FileChangeHandler", and you also need to wrap it all in a separate FileChangeLogger class. Luckily, in C# 2.0, they added Anonymous Delegates, which makes this much nicer:
watcher.FileChanged += delegate(string source_path) { Console.WriteLine(String.Format("{0} changed.", source_path)); }And in C# 3.0, they've made it even nicer!
watcher.FileChanged += (source_path => Console.WriteLine(String.Format("{0} changed.", source_path)));C# 3.0 has an event system that's downright slick, with type-inferencing and everything. I don't think it gets much better than that.
Actually, there is one thing. If there's no handler registered with the event, calling "FileChanged()" will blow up because it sees FileChanged == null until a handler is registered. This means that you have to write "if(Event != null){Event(...):}" every single time you fire the event. Every single time. If you forget, your code will seem to work fine until there's no handler, in which case it will blow up and you'll smack your forhead because you forgot that you have to repeat that line of code every single time you fire an event. I really mean every single time. It's by far the worst wart on an otherwise elgant system. I have no idea why the designers of C# thought this was a good idea. When would you ever want to fire and event and have it blow up in your face?
Anyway, let's try a different programming language, perhaps Java. It has the worst implementation of events I've ever seen. Here's our FileWatcher example:
...
...
Ok, nevermind, I don't have the heart. I can imagine the code full of IListeners, and implementations, and keeping an array of them, and iterating over them, etc, and I just can't do it. I got seriously upset at one useless line in C#. In Java, it's at least 10 times worse. If you really have the stomach for it, go look at http://java.sun.com/docs/books/tutorial/uiswing/events/index.html. To me, it appears that in Java, events are one giant hack around the lack of first-class functions. If Java had first-class functions, none of that nonsense would be necessary.
Now that we've seen a good implementation of events in C# and avoided a bad one in Java, let's make one for Python. I'd rather it be like the C# event system, so let's see what our example would look like:
from Event import Event class FileWatcher: def __init__(self): self.fileChanged = Event() def watchFiles(self): ... self.fileChanged(source_path) ... def log_file_change(source_path): print "%r changed." % (source_path,) watcher = FileWatcher() watcher.fileChanged += log_file_changeI think that looks pretty good. So what does the implementation of Event look like?
class Event(IEvent): def __init__(self): self.handlers = set() def handle(self, handler): self.handler.add(handler) return self def unhandle(self, handler): try: self.handlers.remove(handler) except: raise ValueError("Handler is not handling this event, so cannot unhandle it.") return self def fire(self, *args, **kargs): for handler in self.handlers: handler(*args, **kargs) def getHandlerCount(self): return len(self.handlers) __iadd__ = handle __isub__ = unhandle __call__ = fire __len__ = getHandlerCountWow. That was pretty short. Actually, this is one of the reasons I love Python. If the language doesn't have a feature, we can probably add it. We just added one of C#'s best features to Python in 26 lines of code. More importantly, we now have a nice, light-weight, easy-to-use event system for Python.
For all of you how like full examples that you can cut and paste, here is one that you can run. Enjoy!
class Event: def __init__(self): self.handlers = set() def handle(self, handler): self.handlers.add(handler) return self def unhandle(self, handler): try: self.handlers.remove(handler) except: raise ValueError("Handler is not handling this event, so cannot unhandle it.") return self def fire(self, *args, **kargs): for handler in self.handlers: handler(*args, **kargs) def getHandlerCount(self): return len(self.handlers) __iadd__ = handle __isub__ = unhandle __call__ = fire __len__ = getHandlerCount class MockFileWatcher: def __init__(self): self.fileChanged = Event() def watchFiles(self): source_path = "foo" self.fileChanged(source_path) def log_file_change(source_path): print "%r changed." % (source_path,) def log_file_change2(source_path): print "%r changed!" % (source_path,) watcher = MockFileWatcher() watcher.fileChanged += log_file_change2 watcher.fileChanged += log_file_change watcher.fileChanged -= log_file_change2 watcher.watchFiles()
Have you ever seen
ReplyDeletehttp://pydispatcher.sourceforge.net/ ?
not so neat interface, though, but has other values.
vé tết 2019 đi huế
Deletevé tết 2019 đi đà lạt
vé tết 2019 đi thanh hóa
vé tết 2019 đi vinh
vé tết 2019 đi sài gòn
Great Article
DeleteFinal Year Projects for CSE in Python
FInal Year Project Centers in Chennai
Python Training in Chennai
Python Training in Chennai
pydispatcher looks very interesting, but it's not lightweight. The purpose of the event class I wrote is to be very lightweight.
ReplyDeleteTo do anything more complex usually means you've got concurrency involved, for which this event system isn't good enough. At that point, I think message passing (the Actor Model) is the right technique.
The application I am working on right now is VERY concurrent, and so there is lots of message passing. But sometimes, I need something more simple. Thus, I use both my Event class and my Actor class, and they've worked quite well together. I'll share the Actor class in another post.
Yes, of course, it's clear that your goals are different from pydispatcher creators ones.
ReplyDeleteI think, one of the differences, that affected pydispatcher interface, is that pydispatcher supports many-to-many connections between listening points and listeners, not only one-to-many.
If you have large app (i.e. with large DOM tree), and you have N delegates and M listeners waiting for any change, you need to have N*M connections between them.
Of course, you can add one more delegate, but then your code will have to maintain 2 delegates instead of one each time... with pydispatcher, you need just use "Any" option.
I found this out while thinking if adding neat interface and delegates could add value to django.
I thought this was very helpful. Thanks a lot.
ReplyDeleteHi! I really liked your code and I'll use it in my programs. I wanted to include a comment that the code comes from your blog, but I have to ask you if you consider the code useable under GPL/LGPL?
ReplyDeleteThanks,
Alex
Hey!
ReplyDeleteI loved your code and I've used it in a project of mine - thanks!
However, you have not answered me under what license have you provided it. As I am at the point of releasing my project under GPLv3 I will have to replace your implementation with something else, so please please please tell me the terms under which I can use it.
Great work - thank you!
Hi,
ReplyDeletei had to add a "return self" to the __iadd__ __isub__ mapped functions to get this to work.
But i have just started with py, so maybe i overlooked smth.
Finally, I had to drop your code. Anyway, thanks for the great example.
ReplyDeleteHey, this is really pretty.
ReplyDeleteCool, nicely done. The first time I saw "Java" I had an immediate flashback to all that boilerplate code when I used to write Swing...
ReplyDeleteThis code is clever :) . Thanks for the example
ReplyDeleteAxel is a library inspired by this example: http://pypi.python.org/pypi/axel
ReplyDeleteDude really cool example here .. Thanx alot.
ReplyDeletewell done!
ReplyDeleteThat's a really good code. I've modified it to work in multiprocessing.
ReplyDeleteSee multiprocessing example following your great code here:
ReplyDeletehttp://rnovitsky.blogspot.co.il/2012/10/python-event-listener-multiprocessing.html
nice example (coming from a c# and java developer). I especially like the java example ;-)
ReplyDeleteI have read your coding relay very useful python programming language.Thank you for sharing you python coding. Python course in Chennai
ReplyDeleteشركة كشف تسربات المياه بالدمام
ReplyDeleteشركة كشف تسربات بالدمام
شركة كشف تسربات المياه بالخبر
شركة كشف تسربات المياه بالجبيل
شركة كشف تسربات المياه بالاحساء
شركة كشف تسربات المياه بالقطيف
شركة كشف تسربات بالرياض
شركة كشف تسربات المياه بالرياض
كشف تسربات المياه
This blog awesome and i learn a lot about programming from here.The best thing about this blog is that you doing from beginning to experts level.
ReplyDeleteLove from Pprogramming
I appreciate this work amazing post for us I like it.
ReplyDeleteHarvard Business Review HBR Cases Solutions and Analysis
العاب بنات يحتوي موقعنا على تشكيلة من العاب تلبيس بنات متجددة باستمرار وكل مايتعلق بصنف العاب بنات تلبيس ومكياج والعاب طبخ ومرحبا بكم في العاب تلبيس
ReplyDeleteal3ab-banat01
al3ab cooking
Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a .Net developer learn from .Net Core Training in Chennai. or learn thru .Net Core Training in Chennai. Nowadays Dot Net has tons of job opportunities on various vertical industry.
ReplyDeleteor Es6 Training in Chennai. Nowadays JavaScript has tons of job opportunities on various vertical industry.
Thanks for Kanhasoft is the best Python Web Development Company in India. Hire Dedicated Django Developer over 5 years of experience with affordable rates.
ReplyDeleteThanks for the valuable blog.My(https://counfreedise.in/) team thank you for this wonderful blog.
ReplyDeleteNice blog! I love it very much. All the info given by you are really superb. for my research. keep on posting your views.
ReplyDeleteHadoop Training in Chennai
Big Data Training in Chennai
Angularjs Training in Chennai
Web Designing Course in chennai
PHP Training in Chennai
hadoop training in Velachery
hadoop training in Adyar
مرحبا بكم مع اجود واحسن العاب مزارع
ReplyDeleteالتي تجعلك تعيشين داخل العاب المزرعة السعيدة
و ايضا نمدكم العاب طبخلعاب بنات جديدة و العاب بنات
ك تعيشين ايام البنت الجميلة ام ان كنتي من محبي وصفات الطبخ بالخصوص فندعوك لزيارة موقع samira tv
و شكرا لكم
A debt of gratitude is in order for offering this quality data to us. I truly delighted in perusing. Will without a doubt going to impart this URL to my companions. https://tintuyensinh2012.com
ReplyDeleteThe gathering of certified client/crowd information (emails,names and locality)properly oversaw in a CRM, enables you to keep advertising to them and target future events/item dispatch. stage hire Yorkshire
ReplyDeleteVery Helpful and informative blog! Keep sharing such blogsSoftware Development Company in India
ReplyDeleteOn the off chance that it is your first time to give the game a shot, ensure that you have a fundamental information of poker as a game.machine learning course
ReplyDeleteWe use cash with agnostic images on it. Tommy Hilfiger Net Worth
ReplyDeleteThanks For Sharing This Post. I like your writing Style. Piumi Hansamali Biography
ReplyDeleteThe holy messenger's declaration caused a sublime festival. This permits us probably some breathing space with regards to commending the introduction of Jesus. Aaron Rodgers
ReplyDeletei am browsing this website dailly , and get nice facts from here all the time .
ReplyDeleteI think it could be more general if you get a football sports activity. ExcelR Data Analyst Course
ReplyDeleteشركة تنظيف خزانات بالجبيل
ReplyDeleteشركة تنظيف خزانات بالقطيف
شركة تنظيف خزانات بالخبر
شركة تنظيف خزانات بالاحساء
شركة تنظيف خزانات بالدمام
ReplyDeleteشركة نقل اثاث بالرياض
شركة نقل عفش
غسيل سيارات متنقل بالرياض
شركة تنظيف بالرياض انستقرام
شركة عزل اسطح بالمدينة المنورة
ندى المدينة للخدمات المنزلية
شركة تنظيف خزانات بالمدينة المنورة
شركة كشف تسربات المياه بالرياض
Nice Blog...
ReplyDeleteThanks For sharing with us.
by cognex is the AWS Training in Chennai. Cognex offers so many services according to the clients needs.
Liên hệ đặt vé tại Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ Vietnam Airline
vé máy bay từ mỹ về việt nam
ve may bay tu canada ve viet nam
dat ve may bay tu han quoc ve viet nam
Dr. Vivek Galani is a leading expert in skin and hair. At hair transplant clinic in Surat Skin Care, Cosmetic Laser, Hair Transplant & Slimming Center, Dr. Galani offers the most advanced cosmetic and dermatologic care treatments. The clinic uses advanced FUE methods to produce high-quality hair transplants.
ReplyDeleteشركة تسليك بيارات بالرياض
ReplyDeleteشركة تنظيف منازل بالدمام
شركة ترميم منازل بالجبيل
شركة نقل اثاث بالرياض
شركة تنظيف منازل بالرياض
شركة غسيل سيارات بالبخار بالرياض
شركة ترميمات فلل بالرياض
افضل معلم سباك بالرياض
ReplyDeleteشركة تعقيم فلل بالرياض
مؤسسة سباكة وكهرباء بالرياض
شركة مقاولات بالرياض
شركة نظافة منازل بالرياض
غسيل سيارات بالرياض
شركة نقل اثاث بالرياض
شركة غسيل كنب بالرياض
ReplyDeleteشركة تنظيف مجالس بالرياض
شركة تنظيف منازل بالرياض
شركة ترميمات منازل بالقطيف
شركة مقاولات بالخبر
شركة تعقيم منازل بالمدينة المنورة
شركة تنظيف منازل بالطائف
شركة تنظيف بالبخار في الدمام
ReplyDeleteشركة تنظيف منازل بتبوك
شركة تنظيف فلل بالرياض
مؤسسة سباكة وكهرباء بجدة
شركة مقاولات بالقطيف
مؤسسة سباكة وكهرباء بالمدينة المنورة
كمبوند سراي القاهرة الجديدة
ReplyDeleteمشاريع العاصمة الادارية
دايموند تاور العاصمة الإدارية
كابيتال بارك تاور العاصمة الإدارية
بكسل مول العاصمة الإدارية الجديدة
كمبوند كافانا ليك القاهرة الجديدة
ReplyDeleteكمبوند تاج سلطان القاهرة الجديدة
كمبوند لافيردى العاصمة الإدارية الجديدة
مول كابيتال كير العاصمة الإدارية الجديدة
شقق للبيع فى القاهرة الجديدة
شقق العاصمة الإدارية الجديدة
ReplyDeleteالعاصمة الادارية الجديدة
دايموند تاور العاصمة الادارية الجديدة
هاسيندا باي الساحل الشمالي
فوكا باي الساحل الشمالي
بكسل مول العاصمة الإدارية الجديدة
منتجع ماونتن فيو الساحل الشمالي
كمبوند جاليريا مون فالي
I really appreciate the information that you have shared on your Blog. Thanks for shearing this blog.
ReplyDeleteHow to Print With Black Ink Only When Color Is Empty HP
How to Uninstall HP Print And Scan Doctor
How to Fix HP Printer That Prints Blank Pages
How Do I Unpause My Printer
How Do I Download Hp Print and Scan Doctor
WPS Pin Not Working HP Printer
Can’t Find the WPS Pin for my HP Printer
How to Setup Hp Printer to New WiFi
How to Install Printer Driver Windows 10
Informative blog
ReplyDeleteData Science Course in India