diff --git a/hashin.py b/hashin.py
index 6856bcb..f2b3c1e 100755
--- a/hashin.py
+++ b/hashin.py
@@ -430,13 +430,17 @@ def main():
 
     args = parser.parse_args()
 
-    return run(
-        args.packages,
-        args.requirements_file,
-        args.algorithm,
-        args.python_version,
-        verbose=args.verbose,
-    )
+    try:
+        return run(
+            args.packages,
+            args.requirements_file,
+            args.algorithm,
+            args.python_version,
+            verbose=args.verbose,
+        )
+    except PackageError as exception:
+        print(str(exception), file=sys.stderr)
+        return 1
 
 
 if __name__ == '__main__':

Python version typos generate messy exception
Currently, if I specify the python version improperly, or there is no package for that version, I get an exception thrown:
```
$ hashin -p python2.8 -v -r requirements.txt pyasn1==0.2.3
https://pypi.python.org/pypi/pyasn1/json
Traceback (most recent call last):
  File "/Users/hwine/.pyenv/versions/tools3/bin/hashin", line 11, in <module>
    sys.exit(main())
  File "/Users/hwine/.pyenv/versions/3.6.1/envs/tools3/lib/python3.6/site-packages/hashin.py", line 432, in main
    verbose=args.verbose,
  File "/Users/hwine/.pyenv/versions/3.6.1/envs/tools3/lib/python3.6/site-packages/hashin.py", line 104, in run
    run_single_package(spec, *args, **kwargs)
  File "/Users/hwine/.pyenv/versions/3.6.1/envs/tools3/lib/python3.6/site-packages/hashin.py", line 127, in run_single_package
    algorithm=algorithm
  File "/Users/hwine/.pyenv/versions/3.6.1/envs/tools3/lib/python3.6/site-packages/hashin.py", line 399, in get_package_hashes
    python_versions
hashin.PackageError: No releases could be found for 0.2.3 matching Python versions ['python2.8']
```

The last line is great! The traceback doesn't help much in this case.
diff --git a/tests/test_cli.py b/tests/test_cli.py
index af232ad..10e6206 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -142,6 +142,18 @@ class Tests(TestCase):
             'sha256'
         )
 
+    @mock.patch('hashin.parser')
+    @mock.patch('hashin.sys')
+    @mock.patch('hashin.run')
+    def test_main_packageerrors_stderr(self, mock_run, mock_sys, mock_parser):
+        # Doesn't matter so much what, just make sure it breaks
+        mock_run.side_effect = hashin.PackageError('Some message here')
+
+        error = hashin.main()
+        self.assertEqual(error, 1)
+        mock_sys.stderr.write.assert_any_call('Some message here')
+        mock_sys.stderr.write.assert_any_call('\n')
+
     def test_amend_requirements_content_new(self):
         requirements = """
 # empty so far

pip install -e .
parse_log_pytest
pytest
nose mock pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
-e git+https://github.com/peterbe/hashin.git@ac3f43043a3de7e9b87c731d2aeccf7713c1d465#egg=hashin
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mock==5.2.0
nose==1.3.7
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pytest @ file:///croot/pytest_1738938843180/work
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work

name: hashin
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - mock==5.2.0
      - nose==1.3.7
prefix: /opt/conda/envs/hashin

tests/test_cli.py::Tests::test_main_packageerrors_stderr
tests/test_cli.py::Tests::test_as_library tests/test_cli.py::Tests::test_run tests/test_cli.py::Tests::test_run_case_insensitive tests/test_cli.py::Tests::test_run_contained_names
tests/test_cli.py::Tests::test_amend_requirements_content_new tests/test_cli.py::Tests::test_amend_requirements_content_new_similar_name tests/test_cli.py::Tests::test_amend_requirements_content_replacement tests/test_cli.py::Tests::test_amend_requirements_content_replacement_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_single_to_multi tests/test_cli.py::Tests::test_expand_python_version tests/test_cli.py::Tests::test_filter_releases tests/test_cli.py::Tests::test_get_hashes_error tests/test_cli.py::Tests::test_get_latest_version_non_pre_release tests/test_cli.py::Tests::test_get_latest_version_non_pre_release_leading_zeros tests/test_cli.py::Tests::test_get_latest_version_simple tests/test_cli.py::Tests::test_non_200_ok_download tests/test_cli.py::Tests::test_release_url_metadata_python
hashin.py
hashin.py