Misleading error when area file doesn't exist
#### Code Sample, a minimal, complete, and verifiable piece of code

```python
# Your code here
import pyresample.area_config
pyresample.area_config.load_area('file_that_does_not_exist.yaml', 'ease_sh')
```
#### Problem description
The above produces an obscure error when the file to load doesn't exist:
```python-traceback
Traceback (most recent call last):
  File "c:/Users/amsoe/OneDrive/Desktop/python/Untitled-1.py", line 16, in <module>
    area_def = load_area('areas.yaml', 'ease_sh')
  File "C:\Users\amsoe\AppData\Local\Programs\Python\Python38\lib\site-packages\pyresample\area_config.py", line 75, in load_area
    area_list = parse_area_file(area_file_name, *regions)
  File "C:\Users\amsoe\AppData\Local\Programs\Python\Python38\lib\site-packages\pyresample\area_config.py", line 104, in parse_area_file
    return _parse_yaml_area_file(area_file_name, *regions)
  File "C:\Users\amsoe\AppData\Local\Programs\Python\Python38\lib\site-packages\pyresample\area_config.py", line 139, in _parse_yaml_area_file
    area_dict = _read_yaml_area_file_content(area_file_name)
  File "C:\Users\amsoe\AppData\Local\Programs\Python\Python38\lib\site-packages\pyresample\area_config.py", line 123, in _read_yaml_area_file_content
    area_dict = recursive_dict_update(area_dict, tmp_dict)
  File "C:\Users\amsoe\AppData\Local\Programs\Python\Python38\lib\site-packages\pyresample\utils\_init_.py", line 234, in recursive_dict_update
    for k, v in u.items():
AttributeError: 'str' object has no attribute 'items' 
```

#### Expected Output
A nice error that tells me the file I want to load doesn't exist.



diff --git a/.stickler.yml b/.stickler.yml
index 4a6f4e1..1e265f4 100644
--- a/.stickler.yml
+++ b/.stickler.yml
@@ -1,5 +1,6 @@
 linters:
   flake8:
+    python: 3
     fixer: true
     max-line-length: 120
 fixers:
diff --git a/pyresample/area_config.py b/pyresample/area_config.py
index 33b1f06..4178a44 100644
--- a/pyresample/area_config.py
+++ b/pyresample/area_config.py
@@ -18,6 +18,9 @@
 import logging
 import math
 import os
+import io
+import warnings
+import pathlib
 
 import numpy as np
 import yaml
@@ -53,8 +56,11 @@ def load_area(area_file_name, *regions):
 
     Parameters
     ----------
-    area_file_name : str or list
-        One or more paths to area definition files
+    area_file_name : str, pathlib.Path, stream, or list thereof
+        List of paths or streams.  Any str or pathlib.Path will be
+        interpreted as a path to a file.  Any stream will be interpreted
+        as containing a yaml definition.  To read directly from a string,
+        use :func:`load_area_from_string`.
     regions : str argument list
         Regions to parse. If no regions are specified all
         regions in the file are returned
@@ -77,6 +83,31 @@ def load_area(area_file_name, *regions):
     return area_list
 
 
+def load_area_from_string(area_strs, *regions):
+    """Load area(s) from area strings.
+
+    Like :func:`~pyresample.area_config.load_area`, but load from string
+    directly.
+
+    Parameters
+    ----------
+    area_strs : str or List[str]
+        Strings containing yaml definitions.
+    regions : str
+        Regions to parse.
+
+    Returns
+    -------
+    area_defs : AreaDefinition or list
+        If one area name is specified a single AreaDefinition object is returned.
+        If several area names are specified a list of AreaDefinition objects is returned
+    """
+    if isinstance(area_strs, str):
+        area_strs = [area_strs]
+    return load_area([io.StringIO(area_str) for area_str in area_strs],
+                     *regions)
+
+
 def parse_area_file(area_file_name, *regions):
     """Parse area information from area file
 
@@ -108,17 +139,29 @@ def parse_area_file(area_file_name, *regions):
 def _read_yaml_area_file_content(area_file_name):
     """Read one or more area files in to a single dict object."""
     from pyresample.utils import recursive_dict_update
-    if isinstance(area_file_name, str):
+
+    if isinstance(area_file_name, (str, pathlib.Path)):
         area_file_name = [area_file_name]
 
     area_dict = {}
     for area_file_obj in area_file_name:
-        if (isinstance(area_file_obj, str) and
-                os.path.isfile(area_file_obj)):
-            with open(area_file_obj) as area_file_obj:
-                tmp_dict = yaml.safe_load(area_file_obj)
-        else:
+        if isinstance(area_file_obj, io.IOBase):
+            # already a stream
             tmp_dict = yaml.safe_load(area_file_obj)
+        else:
+            # hopefully a path to a file, but in the past a yaml string could
+            # be passed directly, assume any string with a newline must be
+            # a yaml file and not a path
+            if isinstance(area_file_obj, str) and "\n" in area_file_obj:
+                warnings.warn("It looks like you passed a YAML string "
+                              "directly.  This is deprecated since pyresample "
+                              "1.14.1, please use load_area_from_string or "
+                              "pass a stream or a path to a file instead",
+                              DeprecationWarning)
+                tmp_dict = yaml.safe_load(area_file_obj)
+            else:
+                with open(area_file_obj) as area_file_obj:
+                    tmp_dict = yaml.safe_load(area_file_obj)
         area_dict = recursive_dict_update(area_dict, tmp_dict)
 
     return area_dict
diff --git a/pyresample/test/test_utils.py b/pyresample/test/test_utils.py
index 4678e47..cf5dbb3 100644
--- a/pyresample/test/test_utils.py
+++ b/pyresample/test/test_utils.py
@@ -19,6 +19,8 @@
 
 import os
 import unittest
+import io
+import pathlib
 from tempfile import NamedTemporaryFile
 
 import numpy as np
@@ -101,6 +103,13 @@ Number of rows: 425
 Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)""".format(projection)
         self.assertEqual(nh_str, ease_nh.__str__())
 
+    def test_area_file_not_found_exception(self):
+        from pyresample.area_config import load_area
+        self.assertRaises(FileNotFoundError, load_area,
+                          "/this/file/does/not/exist.yaml")
+        self.assertRaises(FileNotFoundError, load_area,
+                          pathlib.Path("/this/file/does/not/exist.yaml"))
+
     def test_not_found_exception(self):
         from pyresample.area_config import AreaNotFound, parse_area_file
         self.assertRaises(AreaNotFound, parse_area_file,
@@ -201,6 +210,7 @@ Area extent: (-0.0812, 0.4039, 0.0812, 0.5428)""".format(projection)
 
     def test_multiple_file_content(self):
         from pyresample import parse_area_file
+        from pyresample.area_config import load_area_from_string
         area_list = ["""ease_sh:
   description: Antarctic EASE grid
   projection:
@@ -233,10 +243,15 @@ Area extent: (-0.0812, 0.4039, 0.0812, 0.5428)""".format(projection)
     upper_right_xy: [5326849.0625, 5326849.0625]
     units: m
 """]
-        results = parse_area_file(area_list)
+        with self.assertWarns(DeprecationWarning):
+            results = parse_area_file(area_list)
         self.assertEqual(len(results), 2)
         self.assertIn(results[0].area_id, ('ease_sh', 'ease_sh2'))
         self.assertIn(results[1].area_id, ('ease_sh', 'ease_sh2'))
+        results2 = parse_area_file([io.StringIO(ar) for ar in area_list])
+        results3 = load_area_from_string(area_list)
+        self.assertEqual(results, results2)
+        self.assertEqual(results, results3)
 
 
 class TestPreprocessing(unittest.TestCase):
['pyresample/area_config.py', 'pyresample/test/test_utils.py', '.stickler.yml']