<h3 dir="auto">Describe the issue:</h3>
<p dir="auto">This may not be a bug, but the behavior is mysterious and unclear to me. Part of the problem is that in trying to recreate an MRE I cannot.</p>
<p dir="auto">The setup is I have two arrays I'm multiplying, one with very small numbers. I use pdb to drop into interactive mode at the exception. Poking around a bit, the error is happening at the multiplication step, and I can recreate it by taking the smallest non-zero value and multiplying it by the second array, e.g.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Pdb) x[x&gt;0].min() * W
*** FloatingPointError: underflow encountered in multiply

## or 

(Pdb) x[x&gt;0].min() * 1e-10
*** FloatingPointError: underflow encountered in double_scalars"><pre class="notranslate"><code class="notranslate">Pdb) x[x&gt;0].min() * W
*** FloatingPointError: underflow encountered in multiply

## or 

(Pdb) x[x&gt;0].min() * 1e-10
*** FloatingPointError: underflow encountered in double_scalars
</code></pre></div>
<p dir="auto">Ok, the behavior I would like is for this to just go to zero — I don't care about the loss of precision. But then I try to create an MRE to experiment with solutions. What is the minimum?</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(Pdb) y =  x[x&gt;0]
(Pdb) y.min()
9.117510882823816e-308"><pre class="notranslate"><code class="notranslate">(Pdb) y =  x[x&gt;0]
(Pdb) y.min()
9.117510882823816e-308
</code></pre></div>
<p dir="auto">Then I try in a new Python session,</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; np.array([9.117510882823816e-308], dtype='float64')
array([9.11751088e-308])
&gt;&gt;&gt; f = np.array([9.117510882823816e-308], dtype='float64')
&gt;&gt;&gt; f * 1e-10
array([9.11751e-318])
# No error"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; np.array([9.117510882823816e-308], dtype='float64')
array([9.11751088e-308])
&gt;&gt;&gt; f = np.array([9.117510882823816e-308], dtype='float64')
&gt;&gt;&gt; f * 1e-10
array([9.11751e-318])
# No error
</code></pre></div>
<p dir="auto">I then think that this is because of the loss of precision in printing the float. I wasn't sure how to handle this, but I tried <code class="notranslate">np.set_printoptions(precision=1000)</code> but this seems to only impact how arrays are printed, not the <code class="notranslate">np.float64</code> values as they're pulled out. So I next thought I can work with the raw data.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(Pdb) y.min().tobytes()
b'\xe4\x94\x10\xf0\xf6c0\x00'"><pre class="notranslate"><code class="notranslate">(Pdb) y.min().tobytes()
b'\xe4\x94\x10\xf0\xf6c0\x00'
</code></pre></div>
<p dir="auto">Then in the second session,</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ python
Python 3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0] on linux
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; np.frombuffer(b'\xe4\x94\x10\xf0\xf6c0\x00', dtype='float64')
array([9.11751088e-308])
&gt;&gt;&gt; f = np.frombuffer(b'\xe4\x94\x10\xf0\xf6c0\x00', dtype='float64')
&gt;&gt;&gt; f * 1e-10
array([9.11751e-318])
# No error again! "><pre class="notranslate"><code class="notranslate">$ python
Python 3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; np.frombuffer(b'\xe4\x94\x10\xf0\xf6c0\x00', dtype='float64')
array([9.11751088e-308])
&gt;&gt;&gt; f = np.frombuffer(b'\xe4\x94\x10\xf0\xf6c0\x00', dtype='float64')
&gt;&gt;&gt; f * 1e-10
array([9.11751e-318])
# No error again! 
</code></pre></div>
<p dir="auto">I find it odd that I can't create an MRE even with the buffer. What could be going on here?</p>
<p dir="auto">I also tried using format strings,</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(Pdb) f&quot;{y:.10000000}&quot;
'9.117510882823815665548977178863615628591324749590460596300089284407848522066006531932055383210337983249882939129197635693204683436837619342899485403616406753151023440802800570432302810469374755878262353843400205063415657530940618334968743282787718401379326462405248209351474798409859277445681925875157863523372638365924454046245513719836560774569949082153016343041264284375069892098945977461004851844859972461215974549935010425299501133344015649450602626874461701983236523291202172361897246010705343303184104772030271936525192961955598148050240545429201711268321687328347974353590798632145138753708909956222270239479037724670024066080647006736702136140242161352259516590652676898809691225616065391385488011421236917205938345143412249171888106502592563629150390625e-308'"><pre class="notranslate"><code class="notranslate">(Pdb) f"{y:.10000000}"
'9.117510882823815665548977178863615628591324749590460596300089284407848522066006531932055383210337983249882939129197635693204683436837619342899485403616406753151023440802800570432302810469374755878262353843400205063415657530940618334968743282787718401379326462405248209351474798409859277445681925875157863523372638365924454046245513719836560774569949082153016343041264284375069892098945977461004851844859972461215974549935010425299501133344015649450602626874461701983236523291202172361897246010705343303184104772030271936525192961955598148050240545429201711268321687328347974353590798632145138753708909956222270239479037724670024066080647006736702136140242161352259516590652676898809691225616065391385488011421236917205938345143412249171888106502592563629150390625e-308'
</code></pre></div>
<p dir="auto">Then, in the interactive python session I pasted this in</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; ff = np.array([9.117510882823815665548977178863615628591324749590460596300089284407848522066006531932055383210337983249882939129197635693204683436837619342899485403616406753151023440802800570432302810469374755878262353843400205063415657530940618334968743282787718401379326462405248209351474798409859277445681925875157863523372638365924454046245513719836560774569949082153016343041264284375069892098945977461004851844859972461215974549935010425299501133344015649450602626874461701983236523291202172361897246010705343303184104772030271936525192961955598148050240545429201711268321687328347974353590798632145138753708909956222270239479037724670024066080647006736702136140242161352259516590652676898809691225616065391385488011421236917205938345143412249171888106502592563629150390625e-308], dtype='float64')
&gt;&gt;&gt; ff
array([9.11751088e-308])
&gt;&gt;&gt; ff * 1e-10
array([9.11751e-318])
# still no error!"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; ff = np.array([9.117510882823815665548977178863615628591324749590460596300089284407848522066006531932055383210337983249882939129197635693204683436837619342899485403616406753151023440802800570432302810469374755878262353843400205063415657530940618334968743282787718401379326462405248209351474798409859277445681925875157863523372638365924454046245513719836560774569949082153016343041264284375069892098945977461004851844859972461215974549935010425299501133344015649450602626874461701983236523291202172361897246010705343303184104772030271936525192961955598148050240545429201711268321687328347974353590798632145138753708909956222270239479037724670024066080647006736702136140242161352259516590652676898809691225616065391385488011421236917205938345143412249171888106502592563629150390625e-308], dtype='float64')
&gt;&gt;&gt; ff
array([9.11751088e-308])
&gt;&gt;&gt; ff * 1e-10
array([9.11751e-318])
# still no error!
</code></pre></div>
<p dir="auto">So I'm at a loss as to how to create an MRE of this underflow (and how to get the behavior I see and want in the interactive session, that is, it just goes to zero). Apologies if I'm missing something.</p>
<h3 dir="auto">Reproduce the code example:</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# create the MRE is part of the bug, see above"><pre class="notranslate"><span class="pl-c"># create the MRE is part of the bug, see above</span></pre></div>
<h3 dir="auto">Error message:</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Runtime information:</h3>
<p dir="auto">Pdb session:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(Pdb) import sys, numpy; print(numpy.__version__); print(sys.version)
1.24.1
3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0]"><pre class="notranslate"><code class="notranslate">(Pdb) import sys, numpy; print(numpy.__version__); print(sys.version)
1.24.1
3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0]
</code></pre></div>
<p dir="auto">Second session:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import sys, numpy; print(numpy.__version__); print(sys.version)
1.24.1
3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0]
"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; import sys, numpy; print(numpy.__version__); print(sys.version)
1.24.1
3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07)
[GCC 9.4.0]

</code></pre></div>
<h3 dir="auto">Context for the issue:</h3>
<p dir="auto">This is important because I cannot create a working MRE due to the bug. The behavior is different even though I used the raw bytes to try to recreate the example. It would be helpful too if there was documentation on how to create a proper MRE given precision/underflow issues.</p>
<p dir="auto">While it is threadsafe, the <code class="notranslate">with</code> statement gives the false impression that it's always safe. It is not:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="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(&quot;foo: Failed to raise!&quot;)
                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(&quot;bar: raised anyway!&quot;)
                await asyncio.sleep(0.11)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(foo(), bar()))
loop.close()"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">asyncio</span>
<span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>

<span class="pl-k">def</span> <span class="pl-en">divide_by_zero</span>():
    <span class="pl-s1">np</span>.<span class="pl-en">float64</span>(<span class="pl-c1">1</span>) <span class="pl-c1">/</span> <span class="pl-c1">0</span>

<span class="pl-k">async</span> <span class="pl-k">def</span> <span class="pl-en">foo</span>():
    <span class="pl-k">for</span> <span class="pl-s1">j</span> <span class="pl-c1">in</span> <span class="pl-en">range</span>(<span class="pl-c1">3</span>):
        <span class="pl-k">with</span> <span class="pl-s1">np</span>.<span class="pl-en">errstate</span>(<span class="pl-s1">divide</span><span class="pl-c1">=</span><span class="pl-s">'raise'</span>):
            <span class="pl-k">for</span> <span class="pl-s1">i</span> <span class="pl-c1">in</span> <span class="pl-en">range</span>(<span class="pl-c1">2</span>):
                <span class="pl-k">try</span>:
                    <span class="pl-en">divide_by_zero</span>()
                <span class="pl-k">except</span> <span class="pl-v">FloatingPointError</span>:
                    <span class="pl-k">pass</span>
                <span class="pl-k">else</span>:
                    <span class="pl-en">print</span>(<span class="pl-s">"foo: Failed to raise!"</span>)
                <span class="pl-k">await</span> <span class="pl-s1">asyncio</span>.<span class="pl-en">sleep</span>(<span class="pl-c1">0.15</span>)

<span class="pl-k">async</span> <span class="pl-k">def</span> <span class="pl-en">bar</span>():
    <span class="pl-k">for</span> <span class="pl-s1">j</span> <span class="pl-c1">in</span> <span class="pl-en">range</span>(<span class="pl-c1">3</span>):
        <span class="pl-k">with</span> <span class="pl-s1">np</span>.<span class="pl-en">errstate</span>(<span class="pl-s1">divide</span><span class="pl-c1">=</span><span class="pl-s">'ignore'</span>):
            <span class="pl-k">for</span> <span class="pl-s1">i</span> <span class="pl-c1">in</span> <span class="pl-en">range</span>(<span class="pl-c1">2</span>):
                <span class="pl-k">try</span>:
                    <span class="pl-en">divide_by_zero</span>()
                <span class="pl-k">except</span> <span class="pl-v">FloatingPointError</span>:
                    <span class="pl-en">print</span>(<span class="pl-s">"bar: raised anyway!"</span>)
                <span class="pl-k">await</span> <span class="pl-s1">asyncio</span>.<span class="pl-en">sleep</span>(<span class="pl-c1">0.11</span>)

<span class="pl-s1">loop</span> <span class="pl-c1">=</span> <span class="pl-s1">asyncio</span>.<span class="pl-en">get_event_loop</span>()
<span class="pl-s1">loop</span>.<span class="pl-en">run_until_complete</span>(<span class="pl-s1">asyncio</span>.<span class="pl-en">gather</span>(<span class="pl-en">foo</span>(), <span class="pl-en">bar</span>()))
<span class="pl-s1">loop</span>.<span class="pl-en">close</span>()</pre></div>
<p dir="auto">gives:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="foo: Failed to raise!
bar: raised anyway!
foo: Failed to raise!"><pre class="notranslate"><code class="notranslate">foo: Failed to raise!
bar: raised anyway!
foo: Failed to raise!
</code></pre></div>
<p dir="auto">because the error-state is thread-local, but asyncio tasks share a thread.</p>
<p dir="auto">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 <code class="notranslate">__yield_enter__</code> and <code class="notranslate">__yield_leave__</code> mechanism, to be notified when control is leaving the suite via a <code class="notranslate">yield</code>/<code class="notranslate">await</code></p>