Repository: ethereum/web3.py

Issue:
web3 import errors in Python 3.12
* Version: 6.13.0
* Python: 3.12, inside a venv
* OS: linux (but is probably applicable to other platforms as well)
* `pip freeze` output:

```
aiohttp==3.9.1
aiosignal==1.3.1
attrs==23.2.0
bitarray==2.9.2
certifi==2023.11.17
charset-normalizer==3.3.2
cytoolz==0.12.2
eth-abi==4.2.1
eth-account==0.10.0
eth-hash==0.5.2
eth-keyfile==0.7.0
eth-keys==0.4.0
eth-rlp==1.0.0
eth-typing==3.5.2
eth-utils==2.3.1
frozenlist==1.4.1
hexbytes==0.3.1
idna==3.6
jsonschema==4.20.0
jsonschema-specifications==2023.12.1
lru-dict==1.2.0
multidict==6.0.4
parsimonious==0.9.0
protobuf==4.25.1
pycryptodome==3.19.1
pyunormalize==15.1.0
referencing==0.32.1
regex==2023.12.25
requests==2.31.0
rlp==4.0.0
rpds-py==0.16.2
toolz==0.12.0
typing_extensions==4.9.0
urllib3==2.1.0
web3==6.13.0
websockets==12.0
yarl==1.9.4
```

### What was wrong?

In certain situations, web3 will raise ImportErrors on python 3.12 if the `setuptools` package is not installed. _In particular, this happens inside a  fresh Python 3.12 venv._ The `setuptools` package automatically installs the `pkg_resources` package, which is used in web3 [here](https://github.com/ethereum/web3.py/blob/8f853f5841fd62187bce0c9f17be75627104ca43/web3/__init__.py#L25). This used to work fine in older Python versions. However, according to the [new changes in 3.12](https://docs.python.org/3/whatsnew/3.12.html):

> gh-95299: Do not pre-install setuptools in virtual environments created with venv. This means that distutils, setuptools, pkg_resources, and easy_install will no longer available by default; to access these run pip install setuptools in the activated virtual environment.

This means that the pkg_resources package is no longer accessible which causes this error.

Among other things, this scenario can occur inside tox tests for projects that have the `web3` package installed and are configured to test against 3.12. This causes such tests to immediately fail because of the ImportError. The workaround, installing setuptools after the venv created, causes unnecessarily long test times, adding about 3 minutes to the run time.

### How can it be fixed?

Given that web3's use of setuptools/pkg_resources is limited to just getting the version number, this should be trivial to fix. Why not open the file with built-in functions such as `open()` and parse it for the version number? I don't think that `web3` should continue to depend on setuptools.


Discussion:

Resolving patch:
diff --git a/web3/__init__.py b/web3/__init__.py
--- a/web3/__init__.py
+++ b/web3/__init__.py
@@ -1,5 +1,15 @@
-from eth_account import Account  # noqa: E402,
-import pkg_resources
+from eth_account import Account  # noqa: E402
+import sys
+
+if sys.version_info.major == 3 and sys.version_info.minor < 8:
+    import pkg_resources
+
+    __version__ = pkg_resources.get_distribution("web3").version
+else:
+    from importlib.metadata import version
+
+    __version__ = version("web3")
+
 
 from web3.main import (
     AsyncWeb3,
@@ -22,7 +32,6 @@
     WebsocketProviderV2,
 )
 
-__version__ = pkg_resources.get_distribution("web3").version
 
 __all__ = [
     "__version__",


Test patch:
diff --git a/tests/core/web3-module/test_import_and_version.py b/tests/core/web3-module/test_import_and_version.py
new file mode 100644
--- /dev/null
+++ b/tests/core/web3-module/test_import_and_version.py
@@ -0,0 +1,5 @@
+def test_import_and_version():
+    import web3
+
+    version = web3.__version__
+    assert isinstance(version, str)