Skip to content

np.errstate is not asyncio-safe #9444

Closed
@eric-wieser

Description

@eric-wieser

While it is threadsafe, the with statement gives the false impression that it's always safe. It is not:

import asyncio
import numpy as np

def divide_by_zero():
    np.float64(1) / 0

async def foo():
    for j in range(3):
        with np.errstate(divide='raise'):
            for i in range(2):
                try:
                    divide_by_zero()
                except FloatingPointError:
                    pass
                else:
                    print("foo: Failed to raise!")
                await asyncio.sleep(0.15)

async def bar():
    for j in range(3):
        with np.errstate(divide='ignore'):
            for i in range(2):
                try:
                    divide_by_zero()
                except FloatingPointError:
                    print("bar: raised anyway!")
                await asyncio.sleep(0.11)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(foo(), bar()))
loop.close()

gives:

foo: Failed to raise!
bar: raised anyway!
foo: Failed to raise!

because the error-state is thread-local, but asyncio tasks share a thread.

I don't know if there is any way this can be fixed - it seems like this might be a python bug, and context managers might need an __yield_enter__ and __yield_leave__ mechanism, to be notified when control is leaving the suite via a yield/await

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions