Repository: dask/dask

Issue:
Bogus divide by zero warning when using dask array scalars
```python
import dask
import numpy as np
print(f"dask version {dask.__version__}")
print(f"numpy version {np.__version__}")

from dask import array as da

a = da.ones((1, ), chunks=(1,))[0]
1 / a

```

```
dask version 2.1.0
numpy version 1.16.4
/home/mark/miniconda3/envs/skdev/lib/python3.7/site-packages/dask/array/core.py:3808: RuntimeWarning: divide by zero encountered in true_divide
  result = function(*args, **kwargs)
Out[20]: dask.array<truediv, shape=(), dtype=float64, chunksize=()>
```

<details> <summary> conda environment</summary>

```
(dask) mark@mark-xps ~                                                                                                                                                                                             
$ conda list                                                                                                                                                                                                       
# packages in environment at /home/mark/miniconda3/envs/dask:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                        main  
bokeh                     1.2.0                    py37_0    conda-forge
bzip2                     1.0.6             h14c3975_1002    conda-forge
ca-certificates           2019.6.16            hecc5488_0    conda-forge
certifi                   2019.6.16                py37_0    conda-forge
click                     7.0                        py_0    conda-forge
cloudpickle               1.2.1                      py_0    conda-forge
cytoolz                   0.10.0           py37h516909a_0    conda-forge
dask                      2.1.0                      py_0    conda-forge
dask-core                 2.1.0                      py_0    conda-forge
distributed               2.1.0                      py_0    conda-forge
freetype                  2.10.0               he983fc9_0    conda-forge
heapdict                  1.0.0                 py37_1000    conda-forge
jinja2                    2.10.1                     py_0    conda-forge
jpeg                      9c                h14c3975_1001    conda-forge
libblas                   3.8.0               10_openblas    conda-forge
libcblas                  3.8.0               10_openblas    conda-forge
libffi                    3.2.1             he1b5a44_1006    conda-forge
libgcc-ng                 9.1.0                hdf63c60_0  
libgfortran-ng            7.3.0                hdf63c60_0  
liblapack                 3.8.0               10_openblas    conda-forge
libopenblas               0.3.6                h6e990d7_4    conda-forge
libpng                    1.6.37               hed695b0_0    conda-forge
libstdcxx-ng              9.1.0                hdf63c60_0  
libtiff                   4.0.10            h57b8799_1003    conda-forge
locket                    0.2.0                      py_2    conda-forge
lz4-c                     1.8.3             he1b5a44_1001    conda-forge
markupsafe                1.1.1            py37h14c3975_0    conda-forge
msgpack-python            0.6.1            py37h6bb024c_0    conda-forge
ncurses                   6.1               hf484d3e_1002    conda-forge
numpy                     1.16.4           py37h95a1406_0    conda-forge
olefile                   0.46                       py_0    conda-forge
openblas                  0.3.6                h6e990d7_4    conda-forge
openssl                   1.1.1c               h516909a_0    conda-forge
packaging                 19.0                       py_0    conda-forge
pandas                    0.24.2           py37hb3f55d8_0    conda-forge
partd                     1.0.0                      py_0    conda-forge
pillow                    6.1.0            py37he7afcd5_0    conda-forge
pip                       19.1.1                   py37_0    conda-forge
psutil                    5.6.3            py37h516909a_0    conda-forge
pyparsing                 2.4.0                      py_0    conda-forge
python                    3.7.3                h33d41f4_1    conda-forge
python-dateutil           2.8.0                      py_0    conda-forge
pytz                      2019.1                     py_0    conda-forge
pyyaml                    5.1.1            py37h516909a_0    conda-forge
readline                  8.0                  hf8c457e_0    conda-forge
setuptools                41.0.1                   py37_0    conda-forge
six                       1.12.0                py37_1000    conda-forge
sortedcontainers          2.1.0                      py_0    conda-forge
sqlite                    3.29.0               hcee41ef_0    conda-forge
tblib                     1.4.0                      py_0    conda-forge
tk                        8.6.9             hed695b0_1002    conda-forge
toolz                     0.10.0                     py_0    conda-forge
tornado                   6.0.3            py37h516909a_0    conda-forge
wheel                     0.33.4                   py37_0    conda-forge
xz                        5.2.4             h14c3975_1001    conda-forge
yaml                      0.1.7             h14c3975_1001    conda-forge
zict                      1.0.0                      py_0    conda-forge
zlib                      1.2.11            h516909a_1005    conda-forge
zstd                      1.4.0                h3b9ef0a_0    conda-forge
```
</details>

xref: https://github.com/scikit-image/scikit-image/pull/4022


Discussion:
My guess is that this comes during the `_meta` computation.  cc @pentschev

I wonder if we should silence all numpy warnings during meta computation?  cc @shoyer 
> My guess is that this comes during the `_meta` computation. cc @pentschev

It does indeed.

> I wonder if we should silence all numpy warnings during meta computation? cc @shoyer

I think this would be better, I'm going to go ahead and send a PR for this and comment in #4951 that we should revisit this later, such that we should perhaps add these warnings back in a "developer mode".

Resolving patch:
diff --git a/dask/array/utils.py b/dask/array/utils.py
--- a/dask/array/utils.py
+++ b/dask/array/utils.py
@@ -108,41 +108,42 @@ def meta_from_array(x, ndim=None, dtype=None):
 
 
 def compute_meta(func, _dtype, *args, **kwargs):
-    args_meta = [meta_from_array(x) if is_arraylike(x) else x for x in args]
-    kwargs_meta = {
-        k: meta_from_array(v) if is_arraylike(v) else v for k, v in kwargs.items()
-    }
-
-    # todo: look for alternative to this, causes issues when using map_blocks()
-    # with np.vectorize, such as dask.array.routines._isnonzero_vec().
-    if isinstance(func, np.vectorize):
-        meta = func(*args_meta)
-    else:
-        try:
-            # some reduction functions need to know they are computing meta
-            if has_keyword(func, "computing_meta"):
-                kwargs_meta["computing_meta"] = True
-            meta = func(*args_meta, **kwargs_meta)
-        except TypeError as e:
-            if (
-                "unexpected keyword argument" in str(e)
-                or "is an invalid keyword for" in str(e)
-                or "Did not understand the following kwargs" in str(e)
-            ):
-                raise
-            else:
+    with np.errstate(all="ignore"):
+        args_meta = [meta_from_array(x) if is_arraylike(x) else x for x in args]
+        kwargs_meta = {
+            k: meta_from_array(v) if is_arraylike(v) else v for k, v in kwargs.items()
+        }
+
+        # todo: look for alternative to this, causes issues when using map_blocks()
+        # with np.vectorize, such as dask.array.routines._isnonzero_vec().
+        if isinstance(func, np.vectorize):
+            meta = func(*args_meta)
+        else:
+            try:
+                # some reduction functions need to know they are computing meta
+                if has_keyword(func, "computing_meta"):
+                    kwargs_meta["computing_meta"] = True
+                meta = func(*args_meta, **kwargs_meta)
+            except TypeError as e:
+                if (
+                    "unexpected keyword argument" in str(e)
+                    or "is an invalid keyword for" in str(e)
+                    or "Did not understand the following kwargs" in str(e)
+                ):
+                    raise
+                else:
+                    return None
+            except Exception:
                 return None
-        except Exception:
-            return None
 
-    if _dtype and getattr(meta, "dtype", None) != _dtype:
-        with ignoring(AttributeError):
-            meta = meta.astype(_dtype)
+        if _dtype and getattr(meta, "dtype", None) != _dtype:
+            with ignoring(AttributeError):
+                meta = meta.astype(_dtype)
 
-    if np.isscalar(meta):
-        meta = np.array(meta)
+        if np.isscalar(meta):
+            meta = np.array(meta)
 
-    return meta
+        return meta
 
 
 def allclose(a, b, equal_nan=False, **kwargs):


Test patch:
diff --git a/dask/array/tests/test_array_core.py b/dask/array/tests/test_array_core.py
--- a/dask/array/tests/test_array_core.py
+++ b/dask/array/tests/test_array_core.py
@@ -4049,11 +4049,14 @@ def test_auto_chunks_h5py():
 
 
 def test_no_warnings_from_blockwise():
-    x = da.ones((15, 15), chunks=(5, 5))
-
     with pytest.warns(None) as record:
+        x = da.ones((15, 15), chunks=(5, 5))
         (x.dot(x.T + 1) - x.mean(axis=0)).std()
+    assert not record
 
+    with pytest.warns(None) as record:
+        x = da.ones((1,), chunks=(1,))
+        1 / x[0]
     assert not record