Repository: Qiskit/qiskit

Issue:
MissingOptionalLibraryError for pillow
### Environment

- **Qiskit Terra version**: 56c2b86ea601e58ae53241c4f7086ecfb93363e3
- **Python version**: 3.9.6
- **Operating system**: RHEL 8.5


### What is happening?

Qiskit fails to detect pillow even though it is installed.

### How can we reproduce the issue?

1. Create fresh virtual environment
2. Install Qiskit
3. Install requirements from `requirements-dev.txt`
4.
```python
from qiskit import QuantumCircuit
from qiskit.converters import circuit_to_dag

circuit = QuantumCircuit(1)
dag = circuit_to_dag(circuit)
dag.draw()
```
```
---------------------------------------------------------------------------
MissingOptionalLibraryError               Traceback (most recent call last)
<ipython-input-1-e6e6b147a18b> in <module>
      4 circuit = QuantumCircuit(1)
      5 dag = circuit_to_dag(circuit)
----> 6 dag.draw()

~/projects/qiskit-terra/qiskit/dagcircuit/dagcircuit.py in draw(self, scale, filename, style)
   1750         from qiskit.visualization.dag_visualization import dag_drawer
   1751 
-> 1752         return dag_drawer(dag=self, scale=scale, filename=filename, style=style)

~/projects/qiskit-terra/qiskit/utils/lazy_tester.py in out(*args, **kwargs)
    163         def out(*args, **kwargs):
    164             self.require_now(feature)
--> 165             return function(*args, **kwargs)
    166 
    167         return out

~/projects/qiskit-terra/qiskit/visualization/dag_visualization.py in dag_drawer(dag, scale, filename, style)
    225         return None
    226     elif ("ipykernel" in sys.modules) and ("spyder" not in sys.modules):
--> 227         _optionals.HAS_PIL.require_now("dag_drawer")
    228         from PIL import Image
    229 

~/projects/qiskit-terra/qiskit/utils/lazy_tester.py in require_now(self, feature)
    221         if self:
    222             return
--> 223         raise MissingOptionalLibraryError(
    224             libname=self._name, name=feature, pip_install=self._install, msg=self._msg
    225         )

MissingOptionalLibraryError: "The 'pillow' library is required to use 'dag_drawer'. You can install it with 'pip install pillow'."
```

### What should happen?

Pillow should be detected and used.

### Any suggestions?

Perhaps related to one of the following:
- `import pillow` doesn't work, but `import PIL` works
- the package is called Pillow, not pillow


Discussion:
Ah, the trick is that the lazy importer tests by doing `import PIL` and then looking for the name `Image`, since the line I derived it from was `from PIL import Image`.  But in actuality, `Image` is a submodule that's not imported by `import PIL`, so it fails - I didn't completely emulate the `import-from` statement.

This can be fixed most easily by just changing the `HAS_PIL` variable in `qiskit.utils.optionals` to test the module `PIL.Image`, rather than the current set-up of `{"PIL": ("Image",)}`.  A more general solution would be to tweak `LazyImportTester`'s tests to [more faithfully implement the `from x import y` logic](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement).

(Just for interest: all Python package databases are required to be case insensitive and consider hyphens and underscores equivalent.)
@kevinsung Thanks for finding this. I was having the same issue.

Resolving patch:
diff --git a/qiskit/utils/optionals.py b/qiskit/utils/optionals.py
--- a/qiskit/utils/optionals.py
+++ b/qiskit/utils/optionals.py
@@ -253,7 +253,7 @@ def _nlopt_callback(available):
     callback=_nlopt_callback,
     msg="See the documentation of 'qiskit.algorithms.optimizer.nlopts' for installation help",
 )
-HAS_PIL = _LazyImportTester({"PIL": ("Image",)}, name="pillow", install="pip install pillow")
+HAS_PIL = _LazyImportTester("PIL.Image", name="pillow", install="pip install pillow")
 HAS_PYDOT = _LazyImportTester("pydot", install="pip install pydot")
 HAS_PYLATEX = _LazyImportTester(
     {


Test patch: