Repository: modin-project/modin

Issue:
`read_csv` throws error during reading from s3
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Windows 11
- **Modin version** (`modin.__version__`): 06ec64bedc2ace639af09759053182472fdd6544
- **Python version**: 3.8.13
- **Code we can use to reproduce**:

```python
import modin.pandas as pd

s3_path = "s3://dask-data/nyc-taxi/2015/yellow_tripdata_2015-01.csv"
df = pd.read_csv(s3_path, parse_dates=["tpep_pickup_datetime", "tpep_dropoff_datetime"], nrows=10,  storage_options={"anon": True})
print(df)

```

### Describe the problem
`read_csv` throws error during reading from s3. The root cause is unhandled exception here: https://github.com/modin-project/modin/blob/eddfda4b521366c628596dcb5c21775c7f50eec1/modin/core/io/file_dispatcher.py#L276

### Source code / logs

```shell
File "C:\Users\79049\Documents\projects\modin\modin\core\io\text\text_file_dispatcher.py", line 641, in check_parameters_support
    if not cls.file_exists(
  File "C:\Users\79049\Documents\projects\modin\modin\logging\logger_decorator.py", line 128, in run_and_log
    return obj(*args, **kwargs)
  File "C:\Users\79049\Documents\projects\modin\modin\core\io\file_dispatcher.py", line 275, in file_exists
    exists = s3fs.exists(file_path) or exists
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\fsspec\asyn.py", line 86, in wrapper
    return sync(self.loop, func, *args, **kwargs)
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\fsspec\asyn.py", line 66, in sync
    raise return_result
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\fsspec\asyn.py", line 26, in _runner
    result[0] = await coro
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\s3fs\core.py", line 888, in _exists
    await self._info(path, bucket, key, version_id=version_id)
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\s3fs\core.py", line 1140, in _info
    out = await self._call_s3(
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\s3fs\core.py", line 325, in _call_s3
    await self.set_session()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\s3fs\core.py", line 473, in set_session
    self._s3 = await s3creator.__aenter__()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\session.py", line 22, in __aenter__
    self._client = await self._coro
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\session.py", line 102, in _create_client
    credentials = await self.get_credentials()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\session.py", line 133, in get_credentials
    self._credentials = await (self._components.get_component(
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\credentials.py", line 814, in load_credentials
    creds = await provider.load()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\credentials.py", line 486, in load
    metadata = await fetcher.retrieve_iam_role_credentials()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\utils.py", line 175, in retrieve_iam_role_credentials
    token = await self._fetch_metadata_token()
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\utils.py", line 88, in _fetch_metadata_token
    response = await session.send(request.prepare())
  File "C:\Users\79049\.conda\envs\modin\lib\site-packages\aiobotocore\httpsession.py", line 211, in send
    raise EndpointConnectionError(endpoint_url=request.url, error=e)
botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://169.254.169.254/latest/api/token"
```



Discussion:

Resolving patch:
diff --git a/modin/core/io/file_dispatcher.py b/modin/core/io/file_dispatcher.py
--- a/modin/core/io/file_dispatcher.py
+++ b/modin/core/io/file_dispatcher.py
@@ -261,7 +261,10 @@ def file_exists(cls, file_path, storage_options=None):
                 S3FS = import_optional_dependency(
                     "s3fs", "Module s3fs is required to read S3FS files."
                 )
-                from botocore.exceptions import NoCredentialsError
+                from botocore.exceptions import (
+                    NoCredentialsError,
+                    EndpointConnectionError,
+                )
 
                 if storage_options is not None:
                     new_storage_options = dict(storage_options)
@@ -273,7 +276,7 @@ def file_exists(cls, file_path, storage_options=None):
                 exists = False
                 try:
                     exists = s3fs.exists(file_path) or exists
-                except (NoCredentialsError, PermissionError):
+                except (NoCredentialsError, PermissionError, EndpointConnectionError):
                     pass
                 s3fs = S3FS.S3FileSystem(anon=True, **new_storage_options)
                 return exists or s3fs.exists(file_path)
diff --git a/modin/core/io/text/csv_glob_dispatcher.py b/modin/core/io/text/csv_glob_dispatcher.py
--- a/modin/core/io/text/csv_glob_dispatcher.py
+++ b/modin/core/io/text/csv_glob_dispatcher.py
@@ -314,7 +314,10 @@ def file_exists(cls, file_path: str, storage_options=None) -> bool:
                 S3FS = import_optional_dependency(
                     "s3fs", "Module s3fs is required to read S3FS files."
                 )
-                from botocore.exceptions import NoCredentialsError
+                from botocore.exceptions import (
+                    NoCredentialsError,
+                    EndpointConnectionError,
+                )
 
                 if storage_options is not None:
                     new_storage_options = dict(storage_options)
@@ -326,7 +329,7 @@ def file_exists(cls, file_path: str, storage_options=None) -> bool:
                 exists = False
                 try:
                     exists = len(s3fs.glob(file_path)) > 0 or exists
-                except (NoCredentialsError, PermissionError):
+                except (NoCredentialsError, PermissionError, EndpointConnectionError):
                     pass
                 s3fs = S3FS.S3FileSystem(anon=True, **new_storage_options)
                 return exists or len(s3fs.glob(file_path)) > 0
@@ -355,7 +358,7 @@ def get_path(cls, file_path: str) -> list:
             S3FS = import_optional_dependency(
                 "s3fs", "Module s3fs is required to read S3FS files."
             )
-            from botocore.exceptions import NoCredentialsError
+            from botocore.exceptions import NoCredentialsError, EndpointConnectionError
 
             def get_file_path(fs_handle) -> List[str]:
                 file_paths = fs_handle.glob(file_path)
@@ -365,7 +368,7 @@ def get_file_path(fs_handle) -> List[str]:
             s3fs = S3FS.S3FileSystem(anon=False)
             try:
                 return get_file_path(s3fs)
-            except NoCredentialsError:
+            except (NoCredentialsError, EndpointConnectionError):
                 pass
             s3fs = S3FS.S3FileSystem(anon=True)
             return get_file_path(s3fs)


Test patch:
diff --git a/modin/pandas/test/test_io.py b/modin/pandas/test/test_io.py
--- a/modin/pandas/test/test_io.py
+++ b/modin/pandas/test/test_io.py
@@ -940,6 +940,15 @@ def test_read_csv_s3(self, storage_options):
             storage_options=storage_options,
         )
 
+    def test_read_csv_s3_issue4658(self):
+        eval_io(
+            fn_name="read_csv",
+            # read_csv kwargs
+            filepath_or_buffer="s3://dask-data/nyc-taxi/2015/yellow_tripdata_2015-01.csv",
+            nrows=10,
+            storage_options={"anon": True},
+        )
+
     @pytest.mark.parametrize("names", [list("XYZ"), None])
     @pytest.mark.parametrize("skiprows", [1, 2, 3, 4, None])
     def test_read_csv_skiprows_names(self, names, skiprows):