Console introspection helpers and third-party calls to get_ipython()
This came up in explosion/spaCy/issues/3208 (and by proxy, jupyter/notebook#4369 and fastai/fastai#1531) and I've tracked it down to an issue with the way the IPython config is accessed.

If a third-party library or user code accesses nested properties in `get_ipython()` *before*, say, printing a dataframe, the user will see a very confusing and very cryptic error in the `pandas.io.formats.console.in_qtconsole` helper.

**This isn't really pandas' fault, and we'll also be shipping a workaround for this in spaCy with the next version. But it might be worth adding a small fix to pandas as well, just to prevent similar interactions with other libraries and user code** – especially considering that the methods are deprecated and not even needed for IPython 3+.

Also just wanted to let you know, in case others end up reporting this problem here.

#### Code Sample, a copy-pastable example if possible

Consider this minimal example, executed in a Jupyter notebook:

```python
# In[1]:
def test():
    # This is what's executed in pandas.io.formats.console.in_qtconsole
    # and every time the user wants to output a dataframe
    ip = get_ipython()
    front_end = (ip.config.get('KernelApp', {}).get('parent_appname', "") or ip.config.get('IPKernelApp', {}).get('parent_appname', ""))
    front_end.lower()

# In[2]:
test()

# In[3]:
# This is what another third-party package or user code might be running – for instance
# we had this in spaCy in the global scope to check the environment for our visualizers
# (this *used to* be the recommended way to detect an IPython environment)
cfg = get_ipython().config
cfg['IPKernelApp']['parent_appname']

# In[4]:
test()
```
#### Problem description

The last cell raises the following error:

```
<ipython-input-1-d52cc3b6c907> in test()
      3     ip = get_ipython()
      4     front_end = (ip.config.get('KernelApp', {}).get('parent_appname', "") or ip.config.get('IPKernelApp', {}).get('parent_appname', ""))
----> 5     front_end.lower()

AttributeError: 'LazyConfigValue' object has no attribute 'lower'
```

So in a real life scenario, the user renders a dataframe, then imports spaCy or any other package that happens to access the IPython config in the root, renders the dataframe again and sees this error.

#### Expected Output

No error. Maybe there's a way to skip the call to `is_qtconsole` in `DataFrame._repr_html` if it's not relevant to the user's IPython version?

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.7.0.final.0
python-bits: 64
OS: Darwin
OS-release: 18.2.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.24.0
pytest: None
pip: 10.0.1
setuptools: 39.0.1
Cython: None
numpy: 1.16.0
scipy: None
pyarrow: None
xarray: None
IPython: 7.2.0
sphinx: None
patsy: None
dateutil: 2.7.5
pytz: 2018.9
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: None
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml.etree: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None

</details>
