Repository: modin-project/modin
Pull request: DOCS-#4151: Add info in troubleshooting page related to Dask engine usage
Signed-off-by: Alexey Prutskov <alexey.prutskov@intel.com>

<!--
Thank you for your contribution!
Please review the contributing docs: https://modin.readthedocs.io/en/latest/development/contributing.html
if you have questions about contributing.
-->

## What do these changes do?

PR adds info in troubleshooting docs about behavior of Modin on Dask outside of `__main__` block.

- [x] commit message follows format outlined [here](https://modin.readthedocs.io/en/latest/development/contributing.html#commit-message-formatting)
- [ ] passes `flake8 modin/ asv_bench/benchmarks scripts/doc_checker.py` # only doc changes
- [ ] passes `black --check modin/ asv_bench/benchmarks scripts/doc_checker.py` # only doc changes
- [x] signed commit with `git commit -s` <!-- you can amend your commit with a signature via `git commit -amend -s` -->
- [x] Resolves #4151  <!-- issue must be created for each patch -->
- [ ] tests added and passing # only doc changes
- [x] module layout described at `docs/development/architecture.rst` is up-to-date <!-- if you have added, renamed or removed files or directories please update the documentation accordingly -->
- [x] added (Issue Number: PR title (PR Number)) and github username to release notes for next major release <!-- e.g. DOCS-#4077: Add release notes template to docs folder (#4078) -->


Problem statement:
Add info in troubleshooting page related to creating Dask Client in the `main` block
Users can be faced with issues like that when Modin on Dask is used:

```bash
File "/home/u119434/.conda/envs/intel-modin/lib/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
    raise RuntimeError('''
RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
```

Need to provide additional instructions what's it need to do in this case.

Hints from issue discussion:

Commit message: Apply review suggestions

Patch to review:
diff --git a/docs/getting_started/troubleshooting.rst b/docs/getting_started/troubleshooting.rst
index 0476afc989d..bd2815200b3 100644
--- a/docs/getting_started/troubleshooting.rst
+++ b/docs/getting_started/troubleshooting.rst
@@ -217,5 +217,79 @@ This can happen when you use OmniSci engine along with ``pyarrow.gandiva``:
 
 Do not use OmniSci engine along with ``pyarrow.gandiva``.
 
+Error when using Dask engine: ``RuntimeError: if __name__ == '__main__':``
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+The following `script.py` uses Modin with Dask as an execution engine and produces errors:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  df = pd.DataFrame([0,1,2,3])
+  print(df)
+
+A part of the produced errors by the script above would be the following:
+
+.. code-block::
+
+  File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
+    raise RuntimeError('''
+    RuntimeError: 
+        An attempt has been made to start a new process before the
+        current process has finished its bootstrapping phase.
+
+        This probably means that you are not using fork to start your
+        child processes and you have forgotten to use the proper idiom
+        in the main module:
+
+            if __name__ == '__main__':
+                freeze_support()
+                ...
+
+        The "freeze_support()" line can be omitted if the program
+        is not going to be frozen to produce an executable.
+
+This happens because Dask Client uses `fork <https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods>`_
+to start processes.
+
+**Solution**
+
+To avoid the problem need to move Dask Client creating in ``__main__`` scope of the module
+
+The fixed `script.py` is the following:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    df = pd.DataFrame([0,1,2,3]) # Dask Client creating is hidden in a first call of Modin functionality.
+    print(df)
+
+or
+
+.. code-block:: python
+
+  # script.py
+  from distributed import Client
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    client = Client() # Explicit Dask Client creating.
+    df = pd.DataFrame([0,1,2,3])
+    print(df)
+
 .. _issue: https://github.com/modin-project/modin/issues
 .. _Slack: https://modin.org/slack.html
diff --git a/docs/release_notes/release_notes-0.14.0.rst b/docs/release_notes/release_notes-0.14.0.rst
index f02f0b1bd2b..b56abba68bd 100644
--- a/docs/release_notes/release_notes-0.14.0.rst
+++ b/docs/release_notes/release_notes-0.14.0.rst
@@ -30,6 +30,7 @@ Key Features and Updates
 * Documentation improvements
   * DOCS-#4077: Add release notes template to docs folder (#4078)
   * DOCS-#4082: Add pdf/epub/htmlzip formats for doc builds (#4083)
+  * DOCS-#4151: Add info in troubleshooting page related to Dask engine usage (#4152)
 * Dependencies
   * FIX-#4113, FIX-#4116, FIX-#4115: Apply new `black` formatting, fix pydocstyle check and readthedocs build (#4114)
   * TEST-#3227: Use codecov github action instead of bash form in GA workflows (#3226)


Code review comments:
diff_hunk: @@ -217,5 +217,79 @@ This can happen when you use OmniSci engine along with ``pyarrow.gandiva``:
 
 Do not use OmniSci engine along with ``pyarrow.gandiva``.
 
+Error when using Dask engine: ``RuntimeError: if __name__ == '__main__':``
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+The following `script.py` uses Modin with Dask as an execution engine and produces errors:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  df = pd.DataFrame([0,1,2,3])
+  print(df)
+
+A part of the produced errors by the script above would be the following:
+
+.. code-block::
+
+  File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
+    raise RuntimeError('''
+    RuntimeError: 
+        An attempt has been made to start a new process before the
+        current process has finished its bootstrapping phase.
+
+        This probably means that you are not using fork to start your
+        child processes and you have forgotten to use the proper idiom
+        in the main module:
+
+            if __name__ == '__main__':
+                freeze_support()
+                ...
+
+        The "freeze_support()" line can be omitted if the program
+        is not going to be frozen to produce an executable.
+
+This happens because Dask Client uses `fork <https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods>`_
+to start processes.
+
+**Solution**
+
+To avoid the problem need to move Dask Client creating in ``__main__`` scope of the module
path: docs/getting_started/troubleshooting.rst
text: @user1:
```suggestion
To avoid the problem Dask Client creation needs to be moved into ``__main__`` scope of the module.
```

@author:
changed

diff_hunk: @@ -217,5 +217,79 @@ This can happen when you use OmniSci engine along with ``pyarrow.gandiva``:
 
 Do not use OmniSci engine along with ``pyarrow.gandiva``.
 
+Error when using Dask engine: ``RuntimeError: if __name__ == '__main__':``
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+The following `script.py` uses Modin with Dask as an execution engine and produces errors:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  df = pd.DataFrame([0,1,2,3])
+  print(df)
+
+A part of the produced errors by the script above would be the following:
+
+.. code-block::
+
+  File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
+    raise RuntimeError('''
+    RuntimeError: 
+        An attempt has been made to start a new process before the
+        current process has finished its bootstrapping phase.
+
+        This probably means that you are not using fork to start your
+        child processes and you have forgotten to use the proper idiom
+        in the main module:
+
+            if __name__ == '__main__':
+                freeze_support()
+                ...
+
+        The "freeze_support()" line can be omitted if the program
+        is not going to be frozen to produce an executable.
+
+This happens because Dask Client uses `fork <https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods>`_
+to start processes.
+
+**Solution**
+
+To avoid the problem need to move Dask Client creating in ``__main__`` scope of the module
+
+The fixed `script.py` is the following:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    df = pd.DataFrame([0,1,2,3]) # Dask Client creating is hidden in a first call of Modin functionality.
path: docs/getting_started/troubleshooting.rst
text: @user1:
```suggestion
    df = pd.DataFrame([0, 1, 2, 3]) # Dask Client creation is hidden in the first call of Modin functionality.
```

@author:
changed

diff_hunk: @@ -217,5 +217,79 @@ This can happen when you use OmniSci engine along with ``pyarrow.gandiva``:
 
 Do not use OmniSci engine along with ``pyarrow.gandiva``.
 
+Error when using Dask engine: ``RuntimeError: if __name__ == '__main__':``
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+The following `script.py` uses Modin with Dask as an execution engine and produces errors:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  df = pd.DataFrame([0,1,2,3])
+  print(df)
+
+A part of the produced errors by the script above would be the following:
+
+.. code-block::
+
+  File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
+    raise RuntimeError('''
+    RuntimeError: 
+        An attempt has been made to start a new process before the
+        current process has finished its bootstrapping phase.
+
+        This probably means that you are not using fork to start your
+        child processes and you have forgotten to use the proper idiom
+        in the main module:
+
+            if __name__ == '__main__':
+                freeze_support()
+                ...
+
+        The "freeze_support()" line can be omitted if the program
+        is not going to be frozen to produce an executable.
+
+This happens because Dask Client uses `fork <https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods>`_
+to start processes.
+
+**Solution**
+
+To avoid the problem need to move Dask Client creating in ``__main__`` scope of the module
+
+The fixed `script.py` is the following:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    df = pd.DataFrame([0,1,2,3]) # Dask Client creating is hidden in a first call of Modin functionality.
+    print(df)
+
+or
+
+.. code-block:: python
+
+  # script.py
+  from distributed import Client
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    client = Client() # Explicit Dask Client creating.
+    df = pd.DataFrame([0,1,2,3])
path: docs/getting_started/troubleshooting.rst
text: @user1:
```suggestion
    df = pd.DataFrame([0, 1, 2, 3])
```

@author:
changed

diff_hunk: @@ -217,5 +217,79 @@ This can happen when you use OmniSci engine along with ``pyarrow.gandiva``:
 
 Do not use OmniSci engine along with ``pyarrow.gandiva``.
 
+Error when using Dask engine: ``RuntimeError: if __name__ == '__main__':``
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+The following `script.py` uses Modin with Dask as an execution engine and produces errors:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  df = pd.DataFrame([0,1,2,3])
+  print(df)
+
+A part of the produced errors by the script above would be the following:
+
+.. code-block::
+
+  File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
+    raise RuntimeError('''
+    RuntimeError: 
+        An attempt has been made to start a new process before the
+        current process has finished its bootstrapping phase.
+
+        This probably means that you are not using fork to start your
+        child processes and you have forgotten to use the proper idiom
+        in the main module:
+
+            if __name__ == '__main__':
+                freeze_support()
+                ...
+
+        The "freeze_support()" line can be omitted if the program
+        is not going to be frozen to produce an executable.
+
+This happens because Dask Client uses `fork <https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods>`_
+to start processes.
+
+**Solution**
+
+To avoid the problem need to move Dask Client creating in ``__main__`` scope of the module
+
+The fixed `script.py` is the following:
+
+.. code-block:: python
+
+  # script.py
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    df = pd.DataFrame([0,1,2,3]) # Dask Client creating is hidden in a first call of Modin functionality.
+    print(df)
+
+or
+
+.. code-block:: python
+
+  # script.py
+  from distributed import Client
+  import modin.pandas as pd
+  import modin.config as cfg
+
+  cfg.Engine.put("dask")
+
+  if __name__ == "__main__":
+    client = Client() # Explicit Dask Client creating.
path: docs/getting_started/troubleshooting.rst
text: @user1:
```suggestion
    client = Client() # Explicit Dask Client creation.
```

@author:
changed