pallets-eco / blinker Goto Github PK
View Code? Open in Web Editor NEWA fast Python in-process signal/event dispatching system.
Home Page: https://blinker.readthedocs.io
License: MIT License
A fast Python in-process signal/event dispatching system.
Home Page: https://blinker.readthedocs.io
License: MIT License
As of blinker 1.3 we can now reliably use strings as senders, but it seems that the next logical step, using a tuple of strings, does not work reliably.
if I do:
def blah(sender, **kwargs):
print sender, kwargs
s = blinker.Signal()
s.connect(blah, ('ab', 'cde'))
s.send(('ab', 'cde'))
The call to s.send(('ab', 'cde')) will result in blah() sometimes being called, sometimes not.
Using a tuple of strings seems, to me at least, a nice way to have a finer grained signal subscription mechanism without having separate signals.
This morning we faced this issue
for a working service that has received no code change in dependencies recently. By tracking the root cause, I was able to detect that it was caused by typing-extension, which was used by blinker, which was part of Flask (our direct dependency). A similar issue with the same footprint could be found here and here. Typing extension didnt include a change log for version < 4 so I cannot track down which version starts this issue.
We either need to do some if else check to ensure that when a combination of packages is used, blinker is able to use paramspec. Another intrusive way is to declare a minimum version for typing extension.
@jek iirc you can click somewhere in the settings to move a repo to a new github org.
guess that is the easiest option to get it there.
i'ld offer to do some basic maintenance if i get the permissions (like for flatland, including a new pypi release with the new URL).
Hi, I have a use-case of having a signal which only sends once. Currently I solve this, by subclassing Signal
and having a boolean instance variable which is set to true if send
is called. If then send
is called again and the boolean value is true, no real sending is performend.
IMHO, this would be a nice feature for this project and I'm happy to contribute. I opened this issue before to ask if you share my view or not (opinions differ which is fine)
Hey, I am trying to use blinker to process events from the server.
As I subscribe to many contracts, blinker seems to process events too slowly.
So I want to ask you it can support thread or gevent ?
I would like a way of ensuring all receivers are called, even if one misbehaves.
Happy to do a PR if you can give some direction.
Example below (and of course the order of receivers is not specified).
>>> import blinker
... sig = blinker.signal('asignal')
... def a(sender):
... print (sender)
... print ('a done')
... def bad(sender):
... print (sender)
... 1/0
... print ('never done')
... def c(sender):
... print (sender)
... print ('c done')
... sig.connect(a)
... sig.connect(bad)
... sig.connect(c)
... sig.send('THESENDERSTRING')
THESENDERSTRING
a done
THESENDERSTRING
Traceback (most recent call last):
File "<pyshell#2>", line 16, in <module>
sig.send('THESENDERSTRING')
File "D:\Python27\lib\site-packages\blinker\base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "<pyshell#1>", line 8, in bad
1/0
ZeroDivisionError: integer division or modulo by zero
>>>
Is something like the following possible with the current blinker framework?
import time
import multiprocessing
import blinker
sig = blinker.signal('test')
@sig.connect
def callback(data):
print(data)
with multiprocessing.Pool(2) as p:
p.map(sig.send, [1, 2])
Basically, I would like for the signal to create a thread for the callback
function.
Is there any optimal way of doing this currently?
py25: commands succeeded # no python2.5 on my system
py26: commands succeeded # no python2.6 on my system
py27: commands succeeded # ok
py30: commands succeeded # no python3.0 on my system
py31: commands succeeded # no python3.1 on my system
py32: commands succeeded # no python3.2 on my system
py33: commands succeeded # no python3.3 on my system
ERROR: py34: InterpreterNotFound: python3.4 # ok
ERROR: py35: InterpreterNotFound: python3.5 # ok
py36: commands succeeded # ok
ERROR: jython: InterpreterNotFound: jython # ok
So it says "succeeded" although there was no such python interpreter...
CentOS Linux release 7.6.1810 (Core)
[root@VM-4-4-centos ~]# pip3 install blinker
Looking in indexes: http://mirrors.tencentyun.com/pypi/simple
Collecting blinker
Downloading http://mirrors.tencentyun.com/pypi/packages/1b/51/e2a9f3b757eb802f61dc1f2b09c8c99f6eb01cf06416c0671253536517b6/blinker-1.4.tar.gz (111 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 111.5/111.5 KB 7.1 MB/s eta 0:00:00
Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [1 lines of output]
ERROR: Can not execute `setup.py` since setuptools is not available in the build environment.
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed
× Encountered error while generating package metadata.
╰─> See above for output.
note: This is an issue with the package mentioned above, not pip.
hint: See above for details.
then I try to use yum
yum install python-blinker-1.3-2.el7.noarch.rpm
But it only can be used in python2, not have python3, I don't know what can I do.
I see https://centos.pkgs.org/7/centos-extras-x86_64/python-blinker-1.3-2.el7.noarch.rpm.html, the change log in 2014 say it support python3, but actually it not. Or I made a mistake, hope get your help.
Adding blinker to Pipfile's [packages]…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
You can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
Could not find a version that matches vine==1.3.0,==5.0.0
Tried: 0.9.0, 0.9.0, 0.9.1, 0.9.1, 1.0.0, 1.0.0, 1.0.1, 1.0.1, 1.0.2, 1.0.2, 1.1.0, 1.1.0, 1.1.1, 1.1.1, 1.1.2, 1.1.2, 1.1.3, 1.1.3, 1.1.4, 1.1.4, 1.2.0, 1.2.0, 1.3.0, 1.3.0, 5.0.0a1, 5.0.0a1, 5.0.0, 5.0.0
Hello,
It will be nice to add Continuous Integration.
Please go to https://travis-ci.org/ and enable your blinker
project
add a .travis.yml
file with
language: python
python:
- "2.7"
- "3.2"
- "3.3"
- "3.4"
# command to install dependencies
install:
- "pip install ."
# command to run tests
script: nosetests
then you can push your code.
Kind regards
Is dispatch_uid functionality required to reach a feature parity with django signals, or does blinker automatically ensures that's not needed?
I'm basically replacing django.db signals with mongoengine ones, and I want to make sure I'm not introducing bugs because of a missing feature.
https://docs.djangoproject.com/en/4.1/topics/signals/#listening-to-signals
https://docs.djangoproject.com/en/4.1/topics/signals/#preventing-duplicate-signals
Sometimes I have a coil-like topology of objects. In Qt I just used QueuedConnection signal connection for them. Cannot you implement something like that?
import blinker
from blinker import Signal
mega_signal = Signal()
class QueuedObject(object):
def __init__(self):
self.counter = 0
def on_received(self, *args):
print(self.counter)
self.counter += 1
if self.counter <= 50000:
mega_signal.send()
foo = QueuedObject()
mega_signal.connect(foo.on_received)
mega_signal.send()
If I spawn multiple greenlets does blinker signals will find their way among them? In my case it seems that the signals can't travel between greenlets.
Having type hints for this library would make it possible to check its usage in applications with Mypy. I currently have a work-in-progress of those type hints.
Before it can be accepted into python/typeshed, I need to get the permission from the maintainers, so is it OK if I submit Blinker stubs to typeshed?
As the title suggest the release tag is missing for v1.6 in git
Is this project still active? I am asking this since I see lot of old pending PRs.
We have a project where we are using a bunch of signals, but we don't care about the sender in the receiver functions, just the kwargs passed to the signal.
Would it be possible to modify blinker to allow connecting functions without a sender first argument?
Hey @pgjones!
I maintain the Sentry Python Repo and we run tests to make sure our SDK works with the Quart framework. Quart uses Blinker.
With the new release 1.6 our tests fail with the Blinker error RuntimeError: Cannot send to a coroutine function
:
https://github.com/getsentry/sentry-python/actions/runs/4596847777/jobs/8137198226#step:5:608
This is the line in the test that fails:
https://github.com/getsentry/sentry-python/blob/master/tests/integrations/quart/test_quart.py#L147
I am not an expert in Blinker nor Quart, so I do not know why this is happening.
I just wanted to bring to your attention that some behavior changed with the 1.6 release.
After upgrading Blinker from 1.5 to 1.6.2, tests in my project started to fail.
In short, I found this issue and also suggesting a workaround. Whole test case for reproducing this issue is here.
My test cases are checking if a signal was called. I use MagicMock to check if and how signals are called. I also used spec
parameter of MagicMock, because plain initialization did not work for some other compatibility issues, you'll see it below
def foo(sender, **kwargs):
"""Stub function for spec parameter"""
pass
# Test case code
mock = MagicMock(spec=foo)
self.signal.connect(mock, sender=self)
self.signal.send(self) # RuntimeError: Cannot send to a coroutine function here
# see this for details: https://bugs.python.org/issue37251
mock.assert_called_once_with(self)
Error
Traceback (most recent call last):
File "/home/denis/devel/python_scripts/test_blinker.py", line 24, in test_magicmock_spec
self.signal.send(self) # RuntimeError: Cannot send to a coroutine function here
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/base.py", line 298, in send
raise RuntimeError("Cannot send to a coroutine function")
RuntimeError: Cannot send to a coroutine function
So Blinker received async support after the upgrade. The check
asyncio.iscoroutinefunction(func)
has been added to send()
, where func
is my MagicMock. This is indeed a problem
of Python, rather than Blinker, I found this ticket here: https://bugs.python.org/issue37251
spec
But receive another error, at connect()
def test_magicmock(self):
mock = MagicMock()
self.signal.connect(mock, sender=self) # AttributeError: __self__
self.signal.send(self)
mock.assert_called_once_with(self)
Error
Traceback (most recent call last):
File "/home/denis/devel/python_scripts/test_blinker.py", line 30, in test_magicmock
self.signal.connect(mock, sender=self) # AttributeError: __self__
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/base.py", line 131, in connect
receiver_ref = reference(receiver, self._cleanup_receiver)
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/_utilities.py", line 80, in reference
weak = callable_reference(object, callback)
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/_utilities.py", line 91, in callable_reference
return BoundMethodWeakref(target=object, on_delete=callback)
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/_saferef.py", line 124, in __new__
key = cls.calculate_key(target)
File "/home/denis/devel/uvis/venv3/lib/python3.8/site-packages/blinker/_saferef.py", line 190, in calculate_key
return (id(get_self(target)), id(get_func(target)))
File "/usr/lib/python3.8/unittest/mock.py", line 639, in __getattr__
raise AttributeError(name)
AttributeError: __self__
Plain MagicMock does not work. The same for Mock.
Have a callable class and pass it to spec
parameter:
class FooStub:
"""Stub class for spec"""
def __call__(self, sender, **kwargs):
pass
...
def test_magicmock_stub(self):
# This test passes
mock = MagicMock(spec=FooStub)
self.signal.connect(mock, sender=self)
self.signal.send(self)
mock.assert_called_once_with(self)
Also works for Mock.
See the code here
Hi, I stumbled upon an issue when using int
as signal sender
. Receivers where called for some random senders, but not for others.
Please consider this minimal example:
import blinker
my_signal = blinker.Signal()
def handler(sender):
print("Got it!")
my_signal.connect(handler, sender=123456789)
my_signal.send(123456789)
# prints "Got it!"
my_signal.send(123456789 + 0)
# .. nothing ...
This behaviour seems to be caused by comparing senders by id(sender)
, result of which might be different for integers with the same value during lifetime of a program.
One way to fix this, could be to use hash()
instead of id()
. In my opinion it would result in a more intuitive behaviour - e.g. namedtuples and any value objects could be safely used as sender arguments. However, just replacing id(sender)
with hash(sender)
will fail on hash collisions (most notably, hash(-1) == hash(-2)
). Also, that can be a backward incompatible change for some.
Any other ideas?
Is there any support to execute a blocking wait for a specific signal or signals?
Usecase: agent-based modelling where the agents communicate
It seems to not be possible to connect a functools.partial
function to signal.connect()
. Is that intended behavior?
When application uses object proxy as sender in connect then signal is never delivered. This is due use of object id, which is different for real object and proxy.
For example when using https://pypi.python.org/pypi/lazy-object-proxy the signal is never received.
import blinker
from lazy_object_proxy import Proxy
class X(object):
def receive(self, *args, **kwargs):
print 'got signal'
def send(self):
print 'sending signal'
test_signal.send(self)
x = X()
def get_x():
return x
x_proxy = Proxy(get_x) # Lazy object proxy is useful sometimes
test_signal = blinker.Signal()
test_signal.connect(x_proxy.receive, sender=x_proxy)
x_proxy.send() # never received because id(x) != id(x_proxy)
Even though x and x_proxy have different id values, the normal equal comparison works, as well as hash() returns same value:
>>> id(x) == id(x_proxy)
False
>>> x == x_proxy
True
>>> hash(x) == hash(x_proxy)
True
It is similar issue as reported in #30 and similar solution (using hash) would help.
On one of the things I'm working on, blinker.py seems like a perfect solution -- if I could connect receivers that don't take any positional or keyword arguments. That way, I could integrate blinker without having to add an empty positional just to provide access. The necessary modification for this seems fairly light-weight and potentially useful in several cases -- but I'm wondering if it might create unforeseen problems.
In blinker/base.py:
def _get_ret_val(func, val, **kwargs):
try:
ret_val = func(val, **kwargs)
except TypeError:
if val is None:
ret_val = func(**kwargs)
else:
raise
return ret_val
Then, adding it to the final statement in Signal.send...
def send(self, *sender, **kwargs):
if len(sender) == 0:
sender = None
elif len(sender) > 1:
raise TypeError('send() accepts only one positional argument, '
'%s given' % len(sender))
else:
sender = sender[0]
if not self.receivers:
return []
else:
return [(receiver, _get_ret_val(receiver, sender, **kwargs))
for receiver in self.receivers_for(sender)]
The only problem with this I can think of is that None sender might carry special significance; does it?
(Apologies in advance if this is not the place to ask these questions; I'm a bit new to this!)
"AsyncBlink is a small extention to Blinker and enables you to use coroutines as receivers for your signals."
Seems to be essentially a modification of send()
like so:
# the only difference is here. If it's a coroutine,
# run it with asyncio.async()
receivers = self.receivers_for(sender) or []
return_list = []
for receiver in receivers:
ret = receiver(sender, **kwargs)
if asyncio.coroutines.iscoroutine(ret):
ret = asyncio.async(ret)
return_list.append((receiver, ret))
return return_list
Useful to have this in Blinker natively? Perhaps something ala:
def send_async(self, *sender, **kw):
wrapped = lambda v: asyncio.coroutine(lambda: v)
values = [(r, wrapped(v)) if asyncio.iscoroutine(v) else (r, v)
for r, v in self.send(*sender, **kw)]
return asyncio.gather(*values)
cc: @jucacrispim
I have an application that generates reports from a bunch of sources. When a report is generated, a Blinker signal report_created
is called, and one of the receivers sends an email to subscribers of that report type.
It sometimes happens, however, that we want to (re/)generate a large amount of reports. In such cases we don’t want email sending to happen. However, if an actual report gets generated meanwhile by the normal means, i want the receiver to be called, so i can’t just disconnect that receiver.
What i could imagine is something like this:
with report_created.disable():
generate_a_lot_of_reports()
As far as i understand, this is not possible in the current Blinker version, but please correct me if i’m wrong. Also, if this use case seems valid (ie. not a unicorn case, when only my project needs it) i’m willing to dig deeper and submit a PR for this.
As per pallets projects and modern practices.
Hey jek, I am using your blinker as a event-driven
,
when I use a class to create a signals like this
from blinker import signal
from uuid import uuid4
class Appsignal:
def __init__(self):
self.a = signal(uuid4())
when I try to create two objects of Appsinal,
the output id(self.a)
is equal, when I use NamedSignal, it works normally, can you explain why they are equal? or this is a bug.
My code reported this error:
File "/home/lib/python3.4/site-packages/blinker/_saferef.py", line 197, in calculate_key
return (id(get_self(target)), id(get_func(target)))
AttributeError: 'function' object has no attribute 'self' .
When i print(dir(target)) i got this:
['annotations', 'call', 'class', 'closure', 'code', 'defaults', 'delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'get', 'getattribute', 'globals', 'gt', 'hash', 'init', 'kwdefaults', 'le', 'lt', 'module', 'name', 'ne', 'new', 'qualname', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'accept', 'im_func', 'im_self', 'is_signal_handler']
There is no 'self', just 'im_self'. I tried to change the code on line 50 in file _saferef.py:
from if sys.version_info < (3,):
to if sys.version_info > (3,):
and my code works. Is it a mistake in my code or is it a bug ?
Thank you for your patience.
https://github.com/jek/blinker/blob/42aad6110a02a86a9a51a77c75c2d638a50656b7/blinker/base.py#L261
If you don't write the my_signal.send()
call as blinker expects, you get a silent failure.
In my_signal.send(sender=MyObject())
means that sender
is None. I'm on Python3, but I've rigged a simple example to show what is happening. The cases where you don't pass in a named arg it works, but otherwise sender
sticks around in kwargs
).
I'm not sure of a good solution but the way it works definitely caught me off guard.
In [2]: def foo(*sender, **kwargs):
...: print(f"len: {len(sender)} and sender is: {sender}")
...: print(f"kwargs is {kwargs}")
...:
In [3]: foo(123)
len: 1 and sender is: (123,)
kwargs is {}
In [4]: foo(sender=123)
len: 0 and sender is: ()
kwargs is {'sender': 123}
In [5]: foo([123, 'abc'])
len: 1 and sender is: ([123, 'abc'],)
kwargs is {}
Now, if you swap *sender
, to sender=None
, sender
is always defined, even if the len()
fails on an int.
In [6]: def bar(sender=None, **kwargs):
...: print(f"len: {len(sender)} and sender is: {sender}")
...: print(f"kwargs is {kwargs}")
...:
In [7]: bar(123)
TypeError Traceback (most recent call last)
<ipython> in <module>()
----> 1 bar(123)
<ipython> in bar(sender, **kwargs)
1 def bar(sender=None, **kwargs):
----> 2 print(f"len: {len(sender)} and sender is: {sender}")
3 print(f"kwargs is {kwargs}")
4
TypeError: object of type 'int' has no len()
In [8]: bar(sender=123)
TypeError Traceback (most recent call last)
<ipython> in <module>()
----> 1 bar(sender=123)
<ipython> in bar(sender, **kwargs)
1 def bar(sender=None, **kwargs):
----> 2 print(f"len: {len(sender)} and sender is: {sender}")
3 print(f"kwargs is {kwargs}")
4
TypeError: object of type 'int' has no len()
In [9]: bar([123, 'abc'])
len: 2 and sender is: [123, 'abc']
kwargs is {}
I'm not sure if there's a way to reconcile the two approaches, but I figure I might as well write it down.
from setup.py / tox.ini:
[tox]
envlist = py25,py26,py27,py30,py31,py32,py33,py34,py35,jython
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.4',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.0',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
Python 2.6 didn't get new releases since 5 years, so I guess for a new blinker release everything older than 2.7 could be dropped.
The last 3.2 release is also 4y old, so guess all < 3.3 could be dropped (if not even more).
People still using ancient versions can still use the older blinker release(s).
Also, tox and setup.py pypi metadata should be kept in sync.
https://pythonhosted.org/blinker/#blinker.base.Signal.connect_via
We have a use case to send a signal to multiple senders, so we can do:
@some_signal.connect_via_multiple([sender1, sender2, ..., senderN])
def func():
pass
# instead of
@some_signal.connect_via(sender1)
@some_signal.connect_via(sender2)
...
@some_signal.connect_via(senderN)
def func():
pass
@jek Would like to get some opinion from you. Are you leaning on adding a new method connect_via_multiple
that does the same thing as connect_via
except that it accepts senders
as a list, or updating the current connect_via
to accept a senders as either a single sender or list of senders? I will be happy to throw in a PR.
Can I translate the blinker document into Chinese and add to the readme?
There have been several fixes on master since the last release (1.4). Could you release a new version to PyPI?
When running pytest on test suite of my work project I have the following warnings at the end of test run:
.venv/lib/python3.8/site-packages/blinker/base.py:93: 11 warnings
/usr/lib/publishing/.venv/lib/python3.8/site-packages/blinker/base.py:93: DeprecationWarning: invalid escape sequence \*
"""Connect *receiver* to signal events sent by *sender*.
.venv/lib/python3.8/site-packages/blinker/base.py:161: 11 warnings
/usr/lib/publishing/.venv/lib/python3.8/site-packages/blinker/base.py:161: DeprecationWarning: invalid escape sequence \*
"""Connect the decorated function as a receiver for *sender*.
.venv/lib/python3.8/site-packages/blinker/base.py:242: 11 warnings
/usr/lib/publishing/.venv/lib/python3.8/site-packages/blinker/base.py:242: DeprecationWarning: invalid escape sequence \*
"""Emit this signal on behalf of *sender*, passing on \*\*kwargs.
I guess those docstrings should be r"""...""" strings to avoid such warnings. Or \*
sequences should be simply replaced by *
.
Deps:
After upgrading to python3.12, we see these warnings:
/usr/lib/python3/dist-packages/blinker/base.py:93: SyntaxWarning: invalid escape sequence '\*'
"""Connect *receiver* to signal events sent by *sender*.
/usr/lib/python3/dist-packages/blinker/base.py:161: SyntaxWarning: invalid escape sequence '\*'
"""Connect the decorated function as a receiver for *sender*.
/usr/lib/python3/dist-packages/blinker/base.py:242: SyntaxWarning: invalid escape sequence '\*'
"""Emit this signal on behalf of *sender*, passing on \*\*kwargs.
+ /usr/bin/python3 setup.py build_sphinx -b man --build-dir build/sphinx
running build_sphinx
Running Sphinx v4.0.2
making output directory... done
WARNING: html_static_path entry '_static' does not exist
building [mo]: targets for 0 po files that are out of date
building [man]: all manpages
updating environment: [new config] 1 added, 0 changed, 0 removed
reading sources... [100%] index
/home/tkloczko/rpmbuild/BUILD/blinker-1.4/blinker/base.py:docstring of blinker.base.NamedSignal:4: WARNING: Field list ends without a blank line; unexpected unindent.
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
writing... python-blinker.3 { } done
build succeeded, 2 warnings.
till python3.7.4 is ok
The latest version on the PyPi is still 1.6.2 https://pypi.org/project/blinker/#history
I want to use Sourcegraph code search and code review with blinker. A project maintainer needs to enable it to set up a webhook so the code is up-to-date there.
Could you please enable blinker on @sourcegraph by going to https://sourcegraph.com/github.com/jek/blinker and clicking on Settings? (It should only take 15 seconds.)
Thank you!
Exception ignored in: <function BoundMethodWeakref.__init__.<locals>.remove at 0x7f6a4404cae8> Traceback (most recent call last): File "/opt/python/run/venv/local/lib/python3.6/site-packages/blinker/_saferef.py", line 174, in remove NameError: name 'Exception' is not defined Exception ignored in: <function BoundMethodWeakref.__init__.<locals>.remove at 0x7f6a4404ca60> Traceback (most recent call last): File "/opt/python/run/venv/local/lib/python3.6/site-packages/blinker/_saferef.py", line 174, in remove NameError: name 'Exception' is not defined
I think the line 174 except Exception:
in https://github.com/jek/blinker/blob/master/blinker/_saferef.py shoud be only except: in python 3.
Just thought I'd let u know (from having made this same mistake myself),
But the application of @_utilities.lazy_property
isn't actually thread-safe.
An example program you can try:
import threading
import thread
import time
from blinker import _utilities
class SlowThing(object):
@_utilities.lazy_property
def b(self):
print "starting reading 'b' thread %s" % thread.get_ident()
time.sleep(0.5)
print "finished reading 'b' thread %s" % thread.get_ident()
return 1
s = SlowThing()
def _run():
s.b
threads = []
for i in range(0, 5):
t = threading.Thread(target=_run)
threads.append(t)
t.start()
while threads:
t = threads.pop()
t.join()
The output of this will create:
starting reading 'b' thread 140684440516352
starting reading 'b' thread 140684432123648
starting reading 'b' thread 140684423730944
starting reading 'b' thread 140684415338240
starting reading 'b' thread 140684203915008
finished reading 'b' thread 140684432123648
finished reading 'b' thread 140684440516352
finished reading 'b' thread 140684423730944
finished reading 'b' thread 140684415338240
finished reading 'b' thread 140684203915008
So u can see there are many threads at the same time recomputing that property (in this case it doesn't matter, but in other cases it might?)
Some code that I have made that does appear to work fine:
Perhaps we can share it somehow...
https://github.com/openstack/taskflow/blob/master/taskflow/utils/misc.py#L346
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.