Run Idle From a Virtual Environment in Pycharm
Published: 2018-01-31

Lately, I’ve taken to using PyCharm to manage virtual environments. And every once in a while, I enjoy playing around with ideas in Idle, especially when I’m trying out new ideas. Today is one such day, and as I was depending on requests and BeautifulSoup for my code to work, I had to launch Idle from a virtual environment where those packages were installed. And I wanted to do it at the click of a button.

And I wanted to do it at the click of a button.

Adding a virtual environment interpreter in PyCharm Adding a virtual environment interpreter in PyCharm

My (incorrect) solution was essentially based on this Stack Overflow (SO) answer, and had me add run_idle.py to my project:

"""Runner for Idle in a venv."""
from idlelib.idle import main

if __name__ == '__main__':
    main()

This differs from the SO answer in that it imports main from idlelib.idle, not idlelib.PyShell. And it works! “What sort of black magic is this?“, you ask? Well, importing from .PyShell just didn’t work for me. Obviously, at some point, something had changed. So I tried importing from .idle to see if it would work. And it did.

Did you notice I said my solution was incorrect?

Turns out that the author of Automate the Boring Stuff with Python, Al Sweigart, along with Terry J. Reedy, came up with a massive renaming patch for idlelib. The patch was accepted into Python 3.6 (yet another reason to love Python 3.6, isn’t it?). The interesting thing I discovered while having a look at the patch, though, is that the patch renamed idlelib.PyShell to idlelib.pyshell, which I’m not importing. Or am I?

Did you notice I said my solution was incorrect? A quick look at the source code for idlelib in Python 3.6.4 brings me to this revelation:

import os.path
import sys

# Enable running IDLE with idlelib in a non-standard location.
# This was once used to run development versions of IDLE.
# Because PEP 434 declared idle.py a public interface,
# removal should require deprecation.
idlelib_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if idlelib_dir not in sys.path:
    sys.path.insert(0, idlelib_dir)

from idlelib.pyshell import main  # This is subject to change
main()

excerpt from Python-3.6.4/Lib/idlelib/idle.py

Tada! Using idlelib.idle in this way can cause some unexpected behavior down the road. So a quick modification of my little snippet leaves us with a simple script to start Idle from PyCharm, independent of Python versions:

#!/usr/bin/env python
"""Simple script to run Idle from a venv."""

try:
    # Import for Python pre 3.6
    from idlelib.PyShell import main
except ModuleNotFoundError:
    # Import for Python version 3.6 and later
    from idlelib.pyshell import main

if __name__ == '__main__':
    main()

All I have to do now to launch Idle from PyCharm, is to select run_idle.py in the project tool window and hit Ctrl+Alt+F10.

Idle started from within PyCharm Idle started from within PyCharm