Pycharm Book Web PDF
Pycharm Book Web PDF
Effective PyCharm
effectivepycharm.com
Try the accompanying course on PyCharm at https://training.talkpython.fm/ for almost 8
hours of video content.
COPYRIGHT © 2019
May 1, 2019
While every precaution has been taken in the preparation of this book, the publisher and author
assumes no responsibility for errors or omissions, or for damages resulting from the use of the
information contained herein
Contents
Contents
2 Machine Setup 13
2.1 PyCharm Community or PyCharm Professional? . . . . . . . . . . . . . . . . . . . . . 13
2.2 macOS Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Windows Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 Linux Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3 PyCharm Projects 17
3.1 Project Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Creating Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Working with Existing Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 Python Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.5 Managing Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.6 Classifying Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.7 Search Everywhere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.8 Navigating within a project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.10 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4 The Editor 33
4.1 The PyCharm editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2 Simple Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.3 Syntax Highlighting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.4 Code Completion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
v
Contents
4.5 Intention Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.6 Discovering New Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.7 Keymaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.8 Formatting and Code Cleanup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.9 Code Formatting for Teams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.10 Lens Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.11 Object-oriented and Class-based Features . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.12 Viewing Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.13 Creating Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.14 Find Usages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.15 Live Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.16 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.17 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.18 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5 Source Control 57
5.1 Accessing Source Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2 More Source Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
5.3 Branching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.4 Local history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.5 PyCharm and Git Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.6 Pull Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.7 Quick gist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.8 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.9 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6 Refactoring 71
6.1 What is Refactoring? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.2 Finding Duplicate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.3 Renaming items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.4 Introducing variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.5 Creating Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.6 Moving Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
6.8 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
6.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7 Databases 81
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.2 Simple Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.3 Database Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.4 Querying Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.5 Modifying Schemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
7.6 A coding delight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.8 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
vi
Contents
8 Server-side Python Web Applications 89
8.1 Introduction to Server-side Web Applications . . . . . . . . . . . . . . . . . . . . . . . 89
8.2 Creating Server-side Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
8.3 Template Tooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.4 Emmet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.5 Static files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
8.6 Other Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.8 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
11 Packages 119
11.1 Working with Existing Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
11.2 Creating New Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
11.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
11.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
vii
Contents
13.5 Examining Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
13.6 Adding More Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
13.7 Testing Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
13.8 Code Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
13.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
13.10Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
13.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
17 Conclusion 167
17.1 You’ve Done It! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
17.2 Your Turn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
17.3 Thanks and Goodbye . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
viii
Contents
One more thing 179
ix
Foreword
You know what’s easy? When people you admire ask you to write a forward for a book you eagerly
devoured, about a topic that is your primary job.
When Michael and Matt told us they were working on a PyCharm book, frankly, we on the
PyCharm team got quite excited. Talk Python is one of the premier information and training
sources for the world of Python, with a unique talent at communicating the right information in
the right dose in the right tone. PyCharm is a powerful, big tool, which can be overwhelming.
While Michael’s Mastering PyCharm course helps, let’s face it – people like books.
So we knew PyCharm would get the pro treatment and here it is: Effective PyCharm. 16
chapters covering the breadth of all the angles and corners in PyCharm.
As I reviewed the material, I must embarrassingly confide, I frequently found things I...didn’t
know, or don’t use enough in my own coding. For example Duplicated Code in the Refactoring
Chapter. I really enjoy when this happens. PyCharm is an IDE for professionals, with adoption
growing like crazy, and ”IDE” and ”professional” combine to be a tool with a large scope, intended
to be continuously learned. Which makes this book so useful and timely. As another good ”code
smell” about the book: they remind you in Chapter 4 that Local History can save your bacon.
”Effective PyCharm” is well-structured, with code examples, screenshots, and a repository
where the material will be updated. This is an important aspect of such a work. Just like software,
you want to know it will be refined and improved by people willing to stand behind their work. I
also appreciate their commitment to explaining the ”why” as much as the ”what,” which is essential
on a learning journey.
Thank you for buying and studying this book. Not just because we on the PyCharm team
appreciate that you are using our product. But also, thank you for supporting good folks with
good hearts who work hard to independently publish Python material. I give a ”Python 1994”
conference talk about the first years of the Python community. We could never have predicted that
Python 2019 would have an ecosystem able to support folks like Michael and Matt. Of course, it’s
due to such people that it happened.
Again, thank you and I hope you enjoy the book as much as I did.
1
Chapter 1
3
1. Why PyCharm and IDEs?
PyCharm is excellent at building web applications using libraries like Django, Pyramid, or
Flask. It also has a full JavaScript editor and environment so you can use TypeScript or CoffeeScript.
We’ll look into both server-side and client-side features.
PyCharm has a great visual debugger, and we are going to look at all the different features of it.
You can use it to debug and understand your application. It has powerful breakpoint operations
and data visualization that typically editors don’t have.
In Python, we use the concept of packaging to bundle up and share and reuse our libraries.
PyCharm has many features to make and understand these packages. Remember, PyCharm
understands the file structure of packages. It can do automatic imports and even automatically
generate a setup.py file, so you can share your project with others and they can easily install it.
Profiling is a common task if you want to understand how your code is running. If your
application is slow and you want it to go faster, you shouldn’t guess where it is slow. PyCharm
makes it easy to look at the code determine what it fast and slow, rather than relying on our
intuition which may be flawed. PyCharm has some tremendous built-in visual types of tools for
us to fundamentally understand the performance of our app.
PyCharm has built-in test runners for pytest, unittest, and a number of Python testing
frameworks. If you are doing any unit testing or integration testing, PyCharm will come to your
aid. For example, one feature you can turn on is auto test execution. If you are changing certain
parts of your code, PyCharm will automatically re-run the tests.
PyCharm has integrated Jupyter notebooks. It has a special data science view with
documentation and tools to help you explore your data. We will explore data science tools and
how these work in PyCharm.
There are a couple of additional tools that don’t really land in any of the above categories. There
is a chapter with the additional tools at the end.
Last but not least, there are hundreds of plugins that you can get for PyCharm to make it do
other things. For example, do you want it to have like Vim key bindings—there is a plugin for that.
There are many plugins and we will explore a few.
4
1.3. Why choose an IDE?
Studio Code is a GUI application that runs on Mac, Windows, or Linux. It wouldn’t run on the
server when you are ssh-ed in.
There are limitations to using these tools, but they understand more of the structure of projects.
VS Code does have folders, plugins, and excellent editing features. It is more heavyweight than
things like Emacs, and a little more restricted as it is limited where it runs.
Then there’s PyCharm. It understands your code and project structure. It’s more heavyweight,
it takes a little more time to start, a little more space to install, however, it’s worth it.
What we should be optimizing for is programmer productivity, not rapidness of tools or
efficiency of memory or something silly like that. Memory is cheap and our computers are fast.
You should think about where PyCharm lands on the spectrum of editors and IDEs. PyCharm
lands on the far right of the spectrum of editors and IDEs, a big heavyweight tool. But the power
that this tool provides is a well worth it.
5
1. Why PyCharm and IDEs?
Another example is ”You’re trying to call this function on a module that doesn’t exist. Would
you like me to write the function for you, and then you go fill out the details?”
Alternatively, ”I see that you are using an external library however, it’s not listed in your
requirements.txt, shall I add it?”
All these neat little ”code intentions” are fantastic even if you know what you’re doing. The
fact that you don’t have to spend time thinking about it means you can stay in the flow and keep
on writing.
There is excellent source code integration. Git, GitHub, and various other source control
systems are integrated. This is great if you don’t want to leave your environment just to do source
control. Alternatively, if you just prefer a visual environment, PyCharm has source control in the
editor.
The database tooling is super cool in PyCharm. It’s straightforward to understand various
relational databases. If you’re even working with something like SQLAlchemy, there are great
tools to help you understand, explore, and change the database once the schema is created.
PyCharm has package support. This is the ability to create new packages and create the setup
infrastructure or scaffolding. You can then install and register your package on PyPI.
Finally, the unit testing capabilities are excellent. If you’re doing unit tests or even integration
tests, you can write either pytest or a regular unittest. PyCharm can run them and give you code
detailed coverage reports.
There is a lot more than mentioned above and we will cover it much of it in this book.
6
1.5. PyCharm is more than just Python
Figure 11: You can turn on Power Save Mode for a long flight or if you are out of battery at the end of the day.
7
1. Why PyCharm and IDEs?
JetBrains produces many different IDEs: PyCharm, WebStorm (which is for JavaScript and
HTML), AppCode (which is for building IOS apps), DataGrip (for editing databases) and so on.
However, all of these IDEs are built upon a common platform called IntelliJ.
IntelliJ initially was just a Java IDE, but it’s very extensible and configurable. It has been pulled
apart so it can be the foundation of all these different tools. Most things that IntelliJ does, PyCharm
or these other editors can also do.
PyCharm professional is a paid version that you should consider if you need broader tooling
support. If you are working with web applications, JavaScript, or databases, the professional
version has the ability to interface with all of these.
WebStorm is an awesome JavaScript and TypeScript editor. If you’re doing AngularJS, Ionic,
Cordova, or something like that, it’s a great place to work. It understands JavaScript, CSS, HTML
super well. In fact, the pro version of PyCharm has all the features of WebStorm in it.
PyCharm also has the features of a tool called DataGrip. DataGrip is a database IDE from
JetBrains, and all the database functionality within PyCharm comes from there.
When you think of PyCharm, you should think of PyCharm the Python editor, plus WebStorm,
plus DataGrip. This is not a single tool but a holistic, full stack toolset that you can use for anything
to do with web development, database work, or even data science.
1.6 Cross-platform
One of the nice features of PyCharm is that you can use it on any operating system. If you use
Windows, Mac, or some form of Linux, you can use PyCharm, and it will behave in more or less
the same way. (The key bindings might be slightly different-using command on Mac versus control
on Windows or Linux).
If you’re working in teams, where different people have different platforms, or you want to use
it on different machines, you don’t have to worry. PyCharm very much follows the Python ethos
of running everywhere.
8
1.8. PyCharm is open source
1.8 PyCharm is open source
The Community edition of PyCharm is 100% open source. The JetBrains organization in GitHub2
has the community editions. If for some reason PyCharm being open source is something that you
really care about, you can check it out and build it.
I’ve never tried, I have no interest in building PyCharm. Maybe I’d build a plugin, but I
wouldn’t build the whole thing from scratch. Nonetheless, it’s nice to know that the code is there
in case you want to check it out or modify it.
9
1. Why PyCharm and IDEs?
More importantly, and perhaps more challenging, you need to actually recall the features. You
want to keep having this experience: ”Oh yeah, there was this feature, and it was awesome and
here’s the hotkey.” How do you do that?
I’m going to propose a couple of things you can try, adapt them to your learning style.
First, reading about PyCharm is only going to get you so far. It will introduce many of the
features, but if you never try them out you will probably forget them. Make sure you are not just
reading this book, but have a computer nearby where you can try the features of PyCharm.
Next, there is a cheat sheet from JetBrains.3 It has the hotkeys for the most common features.
Print this out and keep it handy.
Learning the hotkeys are a chore, but they pay off. You will be much more productive if you
don’t need to reach for a mouse.
The final learning hack is to use sticky notes. Keep a stack of them handy while reading the
book. As a feature is mentioned, jot the feature and the hotkey from the cheatsheet on the sticky
note.
3
https://blog.jetbrains.com/pycharm/files/2010/07/PyCharm_Reference_Card.pdf
10
1.11. Get the source code on Github
Figure 13: Clicking on the navigate to declaration option when presentation assistant is installed.
You should have a stack of sticky notes. Every week, you should put one (or more) of those on
the corner of your monitor. Make a concerted effort to use that feature and hotkey until it becomes
second nature. Try not to use the mouse if you don’t have to. Once you have it dialed in, put that
sticky note away.
It takes a bit of practice. If you do it for a few days, the hotkeys will stick and you will be more
productive.
One final hint. There is a presentation assistant. If this plugin is enabled and you click on a
command (button or menu item) with your mouse, it will flash the hotkey for a few seconds at the
bottom of the screen.
To install the Presentation Assistant, go to the Preferences page, and type in ”plugin”. From
there click on ”Browse repositories...”. In the search box type ”Presentation Assistant” and click
on the Install button.
An alternative option is the Key Promoter X4 plugin. This plugin will show you the keyboard
shortcut for commands when you use the mouse. Search for ”Key Promoter X” to install the plugin.
5
https://github.com/talkpython/mastering-pycharm-course
11
1. Why PyCharm and IDEs?
1.12 Summary
PyCharm is the most powerful IDE for Python. It runs on the most common operating systems,
Mac, Windows, and Linux. The open source version allows you to create and debug Python
programs. If you are working on web projects or database projects, the professional version has
compelling features to aid you.
Learning a feature-packed tool like PyCharm can be an intimidating task. We recommend that
you print out the cheat sheet, write shortcuts on sticky notes, use the presentation assistant, and
practice using PyCharm with the exercises.
12
Chapter 2
Machine Setup
Note
PyCharm Professional is free for open source developers and for education uses.
I have Python 3.7.1, which will work great for our examples in this book. If instead, you see
this:
You can certainly use PyCharm with Python 2 which macOS bundles, but we will cover some
of the Python 3 only features. If you want access to them (and you do), install Python 3.
You have a couple of options for installing Python 3 on macOS. You can go to http://python.org
and download the latest package there (be sure to choose Python 3). Another option is to use
Homebrew7 , a package manager for Mac similar to Linux. Homebrew is great for installing and
6
https://www.jetbrains.com/pycharm/features/editions_comparison_matrix.html
13
2. Machine Setup
updated all sorts of libraries and applications such as Node, OpenSSL, MongoDB, and of course
Python.
To install Homebrew, copy the command from the webpage and execute it in a terminal:
$ /usr/bin/ruby -e "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/master/install)"
The script explains what it will do and then pauses before it does it. There are more installation
options (required for OS X 10.8 Mountain Lion and below). You will need the command line tools
for XCode installed (see the details8 ).
After installation, you should have access to the brew command. If you have previously
installed Homebrew, be sure to run brew update before continuing. Now you can run:
$ brew install python
It will install a recent version of Python 3 for you. I prefer the Homebrew version because if I
have to compile a Python library that wraps a C or Fortran library, Homebrew usually ”just works”.
Next, we want to install PyCharm. Head over to the download page9 and download the version
you prefer.
After installing PyCharm, you can launch it by double clicking on the icon in your Applications
folder or typing command-space and then PyCharm. We recommend keeping it in your dock for
easy access.
This command will report on the Python version you have or complain that python is not
recognized. In that case, go to http://python.org and download the latest package for Python 3.
Make sure you click on the ”Update PATH” checkbox on the first page of the install wizard so that
you have access to python from the Command Prompt.
Next, we want to install PyCharm. Head over to the download page10 and download the
version you prefer.
You should now be able to run PyCharm from your start menu. We recommend pinning it to
your taskbar for easy access.
7
https://brew.sh
8
https://docs.brew.sh/Installation
9
https://www.jetbrains.com/pycharm/download/
10
https://www.jetbrains.com/pycharm/download/
14
2.4. Linux Setup
2.4 Linux Setup
Most Linux machines come with Python installed. Check it Python 3 is installed by opening a
terminal and typing:
$ python3 --version
Python 3.6.6
If it has a recent version, you’re good. Otherwise, you can use your package manager to install
a newer version.
Next, we want to install PyCharm. Head over to the download page11 and download the
version you prefer.
Then you can pin it to your favorites, so it’s easy to access while going through the book.
11
https://www.jetbrains.com/pycharm/download/
15
Chapter 3
PyCharm Projects
We could clone this with PyCharm, but you’ll see there’s one piece that might get missed from
the application.
Launch PyCharm and click ”Create New Project”. We will create a ”Pure Python” project. In
the location area use a path like first_project. It also asks you to select a Python interpreter.
PyCharm should find the recent version of Python we installed, if not point the ”Interpreter”
selection to it.
If you created a project in a folder already controlled by version control like git, PyCharm shows
a popup asking if you want to add the project to version control. Most of the time, choosing to
register the VCS root is a good idea. It lights up a ton of features around files and source control
inside PyCharm.
On the left-hand side of PyCharm is the project area. You can see your folder, the Python
environment you selected when creating the project, and the external libraries.
If you right-click on the project, you can add a new file by clicking on New > ”Python File”.
PyCharm asks you for the name of the file. Call the file hello. Again, if you are in a version-
controlled directory, it will ask if you want to add that file. In that file put the code:
print("hello world")
17
3. PyCharm Projects
Figure 31: Figure illustrating location and interpreter for the first project.
Figure 32: Figure illustrating a new empty project. Notice VCS popup in lower right
18
3.3. Working with Existing Projects
def other_method():
print("This is the other method")
To run a file, you need to right-click on the hello.py file in the project window and click ”Run
’hello’”.
Running a file in this manner will generate a run configuration. If you look in the upper right-
hand side of PyCharm, you will see a drop-down pointing to the ”hello” configuration. There are
buttons for running, debugging, reporting on code coverage, and profiling the configuration.
Those are the basics are creating a project from scratch. You point PyCharm at a folder, choose
a Python interpreter, and setup run configurations for the top-level files that you add.
In this repository is an apps folder with sorts of different applications or projects. You can have
a mega project with sub-projects in it or a bunch of smaller projects based on the various directories
here. We’ll go for the “mega project”. Before we do thought, let’s also create a virtual environment
for the project. A virtual environment is an isolated Python installation where you can install your
packages and 3rd party dependencies into.
There are two main ways to create a virtual environment. One is from the terminal. This is nice
because it works everywhere and is not dependent on any tool. It is described below. The other
option is to use PyCharm to create the environment.
19
3. PyCharm Projects
Figure 35: Figure illustrating running a file. Output is shown in the lower pane, and the Presentation
Assistant shows the hotkey (shift command R on Mac).
20
3.3. Working with Existing Projects
Figure 36: Figure illustrating buttons for running an existing configuration. There are buttons for running,
debugging, reporting on code coverage, and profiling the configuration.
Note
On commands that work on all platforms (Mac, Windows, and Linux), we will not precede
them with a $ (Unix prompt for Mac or Linux) or a C:\> (Windows prompt). When we invoke
Python for this platform neutral command, we will specify python3 although the command
on Windows will be python. On Windows, because Python does not support the python3 (vs
python) command, you’ll need to be sure that python.exe for Python 3 is first in your path.
An easy way to test this is to type where python in a command prompt.:
$ python3 -m venv .env
To create a virtual environment with PyCharm, open the Preferences window and search for ”Project
Interpreter”. If you click the gear next to the default interpreter, you can click ”Add...”. From
the ”Add Python Interpreter” window, you can create a ”New environment” or use an ”Existing
environment”. If you have multiple versions of Python installed on your machine, make sure that
you have the appropriate ”Base interpreter” selected. Note that PyCharm puts environments in
the .virtualenvs directory in your home folder.
PyCharm lets you open up the python-jumpstart-course-demos folder to create this mega
project. Alternatively, in Mac, if you have PyCharm in your dock, you can drag the folder
over the application icon. Because we have a .env folder with a virtual environment, PyCharm
recognizes it, and uses it as the default run configuration. The names PyCharm recognizes as
virtual environments include venv and .env.
Let’s talk about a concept in PyCharm called Sources Root. Because this project has multiple
subprojects in it, PyCharm will assume that Python package for the project will be in the root
directory. If we navigate to the apps/07_wizard_battle/final folder, there are two files:
actors.py and program.py. If you open program.py, you will see that it references code found in
21
3. PyCharm Projects
Figure 37: Figure illustrating running a file in a folder with an existing virtual environment (.env folder).
actors.py and that it has little red squiggly lines under those references. This is because PyCharm
is looking in the top-level directory for actors.py (and the virtual environment) and not finding
it. However, if we run program.py from PyCharm, it happily runs. When the program is executed,
Python adds the directory containing program.py into the list of paths that it uses to find libraries.
To tell PyCharm to recognize the final folder as a folder containing source code that is stand-
alone relative to the rest of the project, we can right-click on it and choose ”Mark Directory as”,
then ”Sources Root”. This lets PyCharm use its smarts and enables features like autocomplete.
Similarly, if you are working on a web application and have a structure like
apps/static/site.css, PyCharm does not associate /static/site.css to URLs in this
folder. But you can fix this as well. Right-click and choose ”Mark Directory as”, then click
”Resources Root” (as in website resources). PyCharm also lets you make template folders (for
Django, Pyramid, and Flask). You can even tell PyCharm to ignore folders and not analyze or
index them. This can improve indexing speed as well as omit that content from autocompletion.
In conclusion, using an existing project in PyCharm requires opening the folder. If there is a
virtual environment in that folder, PyCharm will automatically detect it and use that environment
to execute the files (only on the initial project creation). We made need to mark folders as source,
resource, or template folders to tell PyCharm how to index and integrate them. To run a file, right-
click on them and choose ”Run” or explicitly create a run configuration.
22
3.4. Python Environments
Figure 38: Figure illustrating marking a folder as a source root, so PyCharm knows to index the code in
them.
If you want to change the environment for a run configuration, you can click on the run
configuration button in the top of the editor. It will either say ”Add Configuration” or the name
the a recently executed file with a dropdown option. Click the dropdown option and click ”Edit
Configurations...”. Note that this will only change the interpreter for the run configuration and
not for the project. (If you want to change the interpreter for the project, you need to do it from the
Preferences -> ”Project Interpreter” page.)
With the ”Run/Debug Configurations” window open you can change the ”Python interpreter”.
For basic scripts using the system Python might be sufficient. For any substantial project, we highly
recommend that you create a virtual environment and use it to manage dependencies.
23
3. PyCharm Projects
Figure 310: Figure illustrating launching the configuration editor. From here we can select the Python
interpreter used for our configuration. Note that each file can have its own configuration.
If you had a virtual environment named .env within the checked out repository before adding
it as a project in PyCharm, PyCharm recognizes that. If you need to add an environment after the
fact, you will need to create the environment and add the environment as a ”Project Interpreter”.
Then you can use the environment from the run configuration window.
You can create an environment using the command line as we have been. But, you can
also create these virtual environments from within PyCharm. To do that, open the ”Settings”
(Windows/Linux Ctrl+Alt+S) or ”Preferences” (Mac) screen (command+”,”) by hitting the wrench
icon. In the search area type ”Interpreter”.
From this window you can see all of the packages in the project interpreter. You can also add,
remove, update, or refresh the packages by clicking on the plus, minus, up arrow, or eye icons
respectively. These icons are found at the bottom of the window. If you click on the gear icon on
the right, there is an option to ”Add...” a new environment. From there you can create a virtual
environment using Python’s venv command, pipenv, conda (if you have Anaconda installed), and
more.
If you are familiar with pip and working from the command line, on the main editor window
there is a button at the bottom labeled ”Terminal” (alt-F12) that launches a terminal.
In this window, you can run all the standard pip commands (e.g. pip install -r
requirements.txt if you have created a requirements file). Whatever interpreter / environment
you have set as the project default will be automatically activated in this window.
24
3.4. Python Environments
Figure 311: Figure illustrating Interpreter configuration. In this screen we can manage packages in an
interpreter. We can also click on the gear to add new interpreters.
25
3. PyCharm Projects
Figure 313: Figure illustrating using the terminal to gain access to pip and the virtual environment. Notice
the ”Terminal” button at the bottom of the window.
Figure 314: Figure illustrating opening a requirements.txt file and PyCharm prompting to install a
missing dependency
Think of each line of the requirements.txt file being fed to pip install VALUE one after
another.
If you open this file in PyCharm, it will recognize if all of the dependencies are met. It will
prompt you to install missing packages.
26
3.6. Classifying Directories
Figure 315: Figure illustrating updating a requirements.txt file after an import for a new package is added
to a Python source file
Conversely, if you install and import a new package and it isn’t installed in your active
environment, PyCharm will prompt you if you want to update the requirements.txt declaring
the new package as a dependency.
27
3. PyCharm Projects
Figure 316: Figure showing ”Search Everywhere” dialog with no search terms entered. In this case, it shows
the most recent files.
Tip
The ”Search Everywhere” command is one of the first you should memorize. Should you forget
another keyboard shortcut or action, you can use ”Search Everywhere” to find it.
28
3.8. Navigating within a project
Figure 317: Figure showing ”Search Everywhere” dialog with pptx entered as the search term. Notice that
it shows classes, files, symbols (functions or methods) and actions.
Figure 318: Figure illustrating holding down command to enable hyperlinking of code and right before
clicking on run function.
to declaration”. PyCharm even has stubs for parts of the standard library that are implemented in
C. When you navigate to those, you won’t see the implementation, but you will see the parameters
and docstring.
The reverse operation, ”Find Usages”, is also available. You can right-click on variable, function,
method, or class and click ”Find Usages” (command + F7 or control + F7).
29
3. PyCharm Projects
3.9 Summary
To get the most out of PyCharm, you need to configure it for new projects. This enables power
tools like autocompletion and code navigation. We saw that PyCharm recognizes existing virtual
environments if they are present in the top-level folder of a project. Alternatively, you can create
them from a terminal or inside of PyCharm. PyCharm will also manage installing third party
dependencies if you don’t want to use pip on the command line.
In some cases, we will need to provide PyCharm with some hints about how to treat directories.
After we have configured our project, we can take advantage of powerful tooling. In this chapter
we also saw some of the search and navigation functionality, but PyCharm has much more to
explore. We will see that in the coming chapters.
3.10 Commands
• ”Run File” - (ctrl-shift-F10)
• ”Terminal” - (alt-F12)
30
3.11. Exercises
3.11 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/1-projects create a new project, run
it, and verify the environment in it.
2. Create a new virtual environment for the previous exercise and set up a run configuration to
use it.
4. Try out the ”navigate to declaration” and ”find usages” commands using the project from
the previous exercise.
31
Chapter 4
The Editor
The service.py file should have a simple stub. We can fill in the details later, but the point is
that this logic will retrieve data about podcasts. Put this content in it:
def download_info():
pass
def get_episode(show_id):
pass
Now let’s show how PyCharm helps you out. We will try and call the download_info method
from inside of program.py. If you simply put download_info() into the body of the main function,
PyCharm will underline the call. This red underline indicates that PyCharm has found a problem
with your code, and possibly some suggestions.
If you move your mouse over the underlined code, a light bulb appears to the left. This indicates
PyCharm has a Code Intention (an automatic fix) for you to activate. The red light bulb color
indicates it can fix an error. If the light bulb were yellow/orange, it would be a suggestion or
an improvement to code that already works.
When you ”Show Intention Actions”, (alt-enter or clicking on the light bulb), you will
be presented with a drop-down of options. These have suggestions such as import
33
4. The Editor
Figure 41: Figure illustrating that when we insert code that a module doesn’t have in its namespace, it
underlines it, indicating there are problems and potential solutions.
Figure 42: Figure illustrating the light bulb that appears when you move your cursor near the underlined
code
Remember we can now navigate between files using ”navigate to declaration”, or hitting shift-
shift to jump to a previous file. You will see that PyCharm has syntax highlighting. Keywords,
built-ins, strings, and user-defined code have their own color. Also if you navigate back to
service.py, you will see that parameter show_id in the get_episode function is underlined
because it is not used.
Unused code is a code smell and may indicate that there is a bug in your logic. Addressing this
bug is a feature PyCharm gives you for free. Some other editors feature this, but more commonly
Python programmers will use a tool like pyflakes to check for these types of issues. By having this
functionality right in your editor, you save time and don’t have to worry about breaking flow to
leave your editor and jump into a terminal or other tool.
34
4.2. Simple Project
Figure 43: Figure illustrating intention actions (hitting alt-enter) when the cursor is over underlined code
Figure 44: Figure illustrating PEP 8 violations. Use reformat code to clean these up.
PyCharm also warns of PEP 8 violations as well. The nice thing about PyCharm is that it doesn’t
just complain, but it also gives you the solution (or multiple solutions) to your problem. By running
the ”Reformat Code” command (alt-command-L or ctrl-alt-L), PyCharm will clean this up for you.
Another option would be to change the import statement from:
from service import download_info
to:
35
4. The Editor
import service
Now if you go into the main function and type service. (notice the period at the
end), PyCharm will present options from the service namespace. Among these options is
download_info.
Inside of the main function let’s add a loop to get information for show ids from 100 to 129.
Update the main function to the code below:
def main()
print("Welcome to the talk python info downloader")
print()
service.download_info()
Now, we will fill in the implementation of download_info. You can nagivate to declaration
(by holding down command or control) and clicking on download_info. This will open up
service.py. We want this function to get information from the RSS feed using the requests12
library. Change the implementation of download_info to this:
36
4.2. Simple Project
Figure 46: Figure illustrating installing the requests library from an intention action
def download_info():
url = 'https://talkpython.fm/episodes/rss'
resp = requests.get(url)
PyCharm will underline requests, as this is not in the namespace of the file. In this case, the
options for intention actions will not do the correct thing (which is to import the requests library).
Instead, pop up to the top of the file and add the line:
import requests
In the intention actions for this line is an option to ”Install package requests”. Selecting that will
install the dependency for us. If there was a requirements.txt file, we would have the option of
updating that as well.
How cool is this? We go from attempting to use an uninstalled, not imported, external package
to having it installed, imported, and (potentially) added to our requirements. All of that with the
slightest bit of a hint to PyCharm.
Now we are going to loop over the results of the RSS feed and pull items out using the element
tree library. Update the download_info function to print out the length of items like this:
def download_info():
url = 'https://talkpython.fm/episodes/rss'
resp = requests.get(url)
resp.raise_for_status()
dom = ElementTree.fromstring(resp.text)
items = dom.findall('channel/item')
print(len(items))
12
https://python-requests.org/
37
4. The Editor
You should be able to use the intention actions to create the correct import for ElementTree as
that is in the standard library. If you jump back to the program.py file and try to run it, nothing
happens because we are not calling the main function. We could type out the common code pattern
below that enables a Python module to operate as both an importable module and an application:
if __name__ == '__main__':
main()
But, let’s have PyCharm do it for us. If you have used Python for a while, this code is commonly
used to indicate that we are executing a file (versus importing it for use as a library). PyCharm has
a feature called Live Templates. If you type main, PyCharm will present a live template for you that
has that conditional in it as the first intention action. Hit TAB while it is selected, and PyCharm
will insert that code for you.
Tip
When you create a main function, PyCharm will add a green gutter icon next to it. This makes
it really easy to run your code.
Live templates are awesome to save time, avoid mistakes, and even help prevent carpal tunnel
issues. You can take advantage of the built-in live templates and later we will show how to create
your own.
If you run the code now, it should tell you how many episodes there are. Let’s continue
updating our code to flush it out and also explore more of PyCharm. In the service.py file
add an import for namedtuple, define a namedtuple to store episode information, and update
the download_info logic, so the code looks like this:
from xml.etree import ElementTree
from collections import namedtuple
import requests
def download_info():
url = 'https://talkpython.fm/episodes/rss'
resp = requests.get(url)
resp.raise_for_status()
dom = ElementTree.fromstring(resp.text)
items = dom.findall('channel/item')
episode_count = len(items)
def get_episode(show_id):
pass
Put the cursor inside of the call to Episode in the for loop. If you hit Parameter Info (command-p
or ctrl-p), PyCharm understands named tuples and will show you the parameters to call it with.
Having parameter information is very useful when calling class initializers, methods, or
functions.
38
4.2. Simple Project
Figure 47: Figure illustrating parameter information when the cursor is inside of a named tuple.
Our next step in our little downloader app is to populate these Episode namedtuples from the
RSS feed. We will need to change the for loop to something like this:
for idx, item in enumerate(items):
episode = Episode(
item.find('title').text,
item.find('link').text,
item.find('pubDate').text,
episode_count - idx - 1
)
episode_data[episode.show_id] = episode
service.download_info()
39
4. The Editor
Note that PyCharm supports f-strings in Python 3.6 and above. It also has completions inside
of them. Sometimes, though PyCharm isn’t smart enough to give us completions. In the above
code, it would not give us completion on the info object, even though we know it is an Episode
named tuple. To help PyCharm, we can take advantage of another Python 3 feature, annotations.
Update the service.py get_episode function to:
def get_episode(show_id: int) -> Episode:
return episode_data.get(show_id)
With the above code, PyCharm gives us completion on the result of calling get_episode!
Note
Since the .get method can return None, the return result of get_episode should really be
typing.Optional[Episode].
A couple of things to note as we were working on this project. You don’t really need to save files.
Whenever you run them PyCharm takes care of that for you. Also, if there is an error during
running, the stacktrace in the terminal window has hyperlinks and you can click them to go to the
source of the error.
This overview should have given you a glimpse into of the power of PyCharm. While amazing,
this is just the surface of what it can do.
40
4.4. Code Completion
Figure 49: Figure illustrating customizing the decorator options for Python code.
There is also an ”Appearance” preference page to future adjust the editor. You can tweak
accessibility, UI options, Window options, and more.
41
4. The Editor
Figure 411: Figure illustrating hitting control space a second time to get more code complete options.
42
4.5. Intention Actions
Figure 412: Figure illustrating the icons for completion on the left. ”f” is for field and ”m” is for method.
On the right are the classes where the attribute is defined. A Wizard is a subclass of Creature which is a
subclass of object.
isn’t able to divine a type for a variable. You have a couple options, you can live without code
completion, add a type annotation to the variable, or add a type annotation for the return type on
the function. The ”Show Intention” command (alt + return) will include an option to ”Add a type
hint”.
43
4. The Editor
Figure 413: Figure illustrating the result of Show Intention (alt + return) on the res variable. We can add a
type hint to the variable, or to the download_info function. This will enable intelligent code completion.
Figure 414: Figure illustrating the bulb icon. You can click on it or type alt + return to bring up the intention
options.
Note
Mac users have another option. In the ”Help” menu is a search box. If you enter ”Reformat”
in there, it brings up a list of menu items and if you select the menu item, it will bring up the
menu and point to where that item is. This works ok if you prefer to use the mouse, but it is
better to remember the hotkeys for frequently used commands.
”Find action” is a powerful command and one of the first you should memorize. For example, if
you wanted to refactor some code into a function, you can highlight that code, open up the find
action window, and type ”refactor”. You will see that you can open up the ”Refactor” menu itself,
or call ”Refactor Method” (command-alt-m, or ctrl-alt-m) directly.
44
4.7. Keymaps
Figure 415: Figure illustrating using the find action popup to search for the command to ”Reformat Code”.
Note
PyCharm uses the term ”method” for refactoring a function (code at the global level or in a
function) or a method (a function bound to in a class).
4.7 Keymaps
All of the actions in PyCharm are configurable. Out of the box these are preconfigured for you and
use the mappings found in the cheat sheet referenced earlier. If you want to customize any keycode,
you can in the Preference window. Search for ”keymap” to open up the screen to adjust them. From
there you can customize individual commands or you can tell PyCharm to use a different keymap.
For example, if you are used to Emacs, there is a Emacs option the ”Keymap” drop-down that has
pretty good emulation for Emacs.
Alternatively, if you are a Vim user, there is a plugin, IdeaVim, that supports many of the Vim
features. You will need to go to the ”Plugins” screen on the preferences page and search for ”vim”.
From there you can click the ”Install” button.
Note
If you change the keymap many of the books in this command will have a different command.
For example Emacs uses control space to mark a selection, so it won’t work for code completion.
45
4. The Editor
Figure 417: Figure illustrating issues found in the code. There are no blank lines and the function name is
not lowercase.
def find_user(username):
return User.objects(name=username).first()
def changeAddress(user,newEmail):
return None
It has PEP 8 violations because there are no spaces between the functions. Also, changeAddress
and newEmail are camel-case, and there is no space before newEmail.
There is a command ”Reformat Code” (cmd + L, or ctrl + L) that will address some of these issues.
The code will look like this following that command:
46
4.9. Code Formatting for Teams
def find_user(username):
return User.objects(name=username).first()
Note
If you want to format a whole project, you can run the Run -> ”Code Cleanup...” action. (There
is no shortcut for this command, but hitting shift + shift and typing in the first letters of the
command will pull up the action. If you prefer to type instead of using the mouse, it is possible
to run this without reaching for the mouse.)
Notice that the name of changeAddress was not converted to a PEP 8 compliant name. In this
case we could use the ”Rename” command (shift-F6) on the function declaration. Note that you
can not do this refactoring on calls to that function, you have to do it on the function itself. If you
come across libraries with non-PEP 8 compliant naming, unless you are the author of third-party
libraries, you will just have to live with that.
15
https://docs.openstack.org/hacking/latest/user/hacking.html
16
https://github.com/google/yapf
17
https://github.com/ambv/black
18
https://plugins.jetbrains.com/plugin/10563-black-pycharm
47
4. The Editor
Figure 418: Figure illustrating changing code style preferences. You can also import and export these settings
from this page.
Figure 419: Figure illustrating setting the scheme to ”Project” so that the project formatting is not global.
48
4.10. Lens Mode
Figure 420: Figure illustrating Lens Mode. To activate lens mode hover the mouse over the stripe in the
scrollbar. If they are outside of the scroll box, the lens mode popup will appear
Configuring formatting is important because it makes interacting with others much easier. The
last thing a code reviewer wants to see when reviewing code is a bunch of whitespace tweaks, with
that single meaningful change to code lost in the noise.
49
4. The Editor
Figure 421: Figure illustrating the gutter icons. On the left of class, __init__, __repr__, and
get_defensive_roll are the gutter icons. The down arrows indicate that there are subclasses (on the class)
or that subclasses override the methods. The up arrows indicate that the method is overriding a base class
(object is the implied base in Python 3)
Figure 422: Figure illustrating hovering over a gutter icon. In this case, it indicates which classes subclass
the Creature class. We can click on the icon to navigate to those classes.
50
4.12. Viewing Documentation
Figure 423: Figure illustrating parameters for the .attack method. Notice that it says a creature should
have a name and get_defensive_roll attribute).
51
4. The Editor
Figure 424: Figure illustrating quick documentation for the .attack method. If there were a docstring on
this method it would be shown. Notice that the type information is present as well (in this case it is inferred).
Figure 425: Figure illustrating the result of inserting triple quotes and hitting enter. PyCharm stubbed out
the parameters and return value.
52
4.15. Live Templates
Figure 426: Figure illustrating the result of calling find usages on the .get_defensive_roll method.
Again, this is more than a simple grep through the files. PyCharm understands how code is
referenced and will present template results as well. If there are multiple classes that happen to
use the same method name, PyCharm should be able to find the correct method and not show the
other method. PyCharm is also able to do intelligent renaming across the whole project.
It would also place the cursor where the comment is in the code above. This is a simple template,
there are others that are more complex, such as typing iter. If you type iter and hit TAB you will
see code like this with CURSOR being the actual cursor rather than the word:
for in CURSOR:
You can type in what you want to enumerate over, say range(10), and then hit TAB again. You
will see the cursor move to right after the for keyword:
for CURSOR in range(10):
You can enter a variable name for iteration, say i, and hit TAB. You will see this:
for i in range(10):
CURSOR
53
4. The Editor
Figure 427: Figure illustrating the live template for the iter abbreviation. You can click the ”Edit variables”
button to change the navigation order of the variables.
You might be wondering, given the template, why the cursor went to $ITERABLE% first instead
of $VAR$. On the right side is a button called ”Edit Variables”. If you click it shows you the order
that the variables are entered. You can reorder them as desired.
If you find yourself repeatedly typing the same code, you can make a template for it. Click
the plus button to create a new template, give it an abbreviation and description, and tell it what
context to run in (ie. Python, XML, etc). This is an easy way to improve productivity, especially if
you can share them with other team members.
4.16 Summary
This chapter covered many commands that will make you productive in PyCharm. If you start
using these commands and the commands from the previous chapter, you will find yourself
leveraging much of the power of PyCharm. We explored using PyCharm to clean up code,
make suggestions, auto-complete, and explore documentation. PyCharm has a very powerful and
configurable editor. Because you will be using it a lot, it pays dividends to invest some time in
learning the features of it.
4.17 Commands
• ”Show Intention Actions” - (alt-enter or clicking on the light bulb)
54
4.18. Exercises
• ”Code Cleanup...”
• ”Rename” - (shift-f6)
4.18 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/2-the-editor to add a feature to a
class.
55
Chapter 5
Source Control
Once you start working with teams, you will need some sort of source control. This makes group
development much easier as you can branch, merge, and commit changes. PyCharm has built-in
support for source control for many of the common systems. If you have ever wanted a UI for
your favorite source control system, you are probably in luck as the common ones are supported
by PyCharm. There is support for Git, Subversion, Mercurial, Perforce, and CVS. Beyond these,
you can find plugins for PyCharm adding additional capabilities such as Microsoft’s TFS.
57
5. Source Control
Figure 51: Figure illustrating clicking on the Git button in the lower right. Notice that the button itself
indicates the current branch. When you click on it, there are menu options to create a new branch or tag as
well as submenus for interacting with other branches.
Figure 52: Figure illustrating buttons for updating the project, committing changes, comparing with the
repository version, showing the history, and reverting. These are found in the upper right of the editor.
”Commit and Push...”. If you decide to push, a ”Push Commits” window opens with opens for
including tags or forcing a push.
PyCharm has some nice options in this UI that are painful or annoying from the command line
tool. If you want to remove a change from a commit, you need to unselect the checkbox next to the
change. This lets you pick and choose the changes you want to commit.
Another cool feature of Git integration is the ”Annotate” command (VCS -> Git -> Annotate).
This allows you to see all the check-ins to a file. If you run this command on the left is a list of who
committed the changes and when. If you click on a change, another screen showing the differences
will appear.
58
5.2. More Source Control
Figure 53: Figure illustrating the Compare with the Same Repository Version screen. On the left is the
repository version and on the right is the local version.
Figure 54: Figure illustrating committing work to a repository. Note that you can check what files to include
and provide some context of the changes in the ”Commit Message” text box.
59
5. Source Control
Figure 55: Figure illustrating the ”Push Commits” window. From here you can include tags, or force a push.
code is a highlight. If the gutter color is green, then that is a new line that was not in a prior commit.
If the color is blue, it indicates that the line was in a prior commit but has since been updated.
If you click on the highlight in the gutter some buttons will appear. You can jump to the
”Previous Change” (ctrl-shift-alt-UP), the ”Next Change” (ctrl-shift-alt-DOWN), ”Rollback Lines”
(command-alt-z, or ctrl-alt-z), ”Show Diff” (command-d or ctrl-d), ”Copy” (command-c, or ctrl-c),
and ”Highlight Words”. Clicking on a blue gutter will also show the difference inline. Note that the
copy command will copy the original version, not the current version.
PyCharm will also insert an arrow pointing to the right. That indicates that a section was deleted
from the repository version. These are nice unobtrusive hints for you to see what has changed in
the file you are editing.
60
5.2. More Source Control
Figure 56: Figure illustrating the annotate view. On the left-hand side is a list of changes made to a file.
Figure 57: Figure illustrating the highlight in the gutter and the context menu that appears when you click
on it. Also shows the arrow where code was deleted.
61
5. Source Control
5.3 Branching
In this section, we will look at creating a new branch and working with it. Recall that in the lower
right-hand portion of PyCharm there is a Git widget button. If you click on it, you will have options
for working with branches. If you wanted to work on a remote feature branch, you can click on
the remote branch name in the popup and then click ”Checkout as new local branch”. At this
point, your project will be updated with the code from that branch. You can follow the previously
described workflow to commit into the remote branch.
Once you have created a new local branch, you can quickly toggle between a branch by clicking
on the local name and then hitting ”Checkout”. If you have local changes, you have two options.
One is to ”Force Checkout”, which will throw away local changes. The other is ”Smart Checkout”,
which will stash the changes, checkout the branch, and then unstash the changes.
PyCharm will also let you merge branches or rebase them. Checkout the branch that you want
to update with the changes. Click on the Git widget and select the branch you want to get the
changes from. You can choose ”Merge into Current”, or ”Checkout with Rebase”. If there are
conflicts, you will have the chance to merge them.
62
5.5. PyCharm and Git Flow
Figure 59: Figure illustrating Local History. Independent of source control, PyCharm manages its own
version of the changes to the project.
them with others. Do be aware that PyCharm caches this information on your machine for the past
five days by default. If you want to change this value, you will need to open the PyCharm Registry
and change the localHistory.daysToKeep parameter and restart PyCharm.
63
5. Source Control
64
5.6. Pull Requests
At this point, you can code away. After you have added the code necessary to address the
GitHub issue, you need to close the task. To do that run the ”Close Active Task” (alt-shift-w). When
you hit ”OK”, you will be presented with the opportunity to push the branch. If you push the
branch, PyCharm will commit the branch on GitHub and put you back on the latest version of
master. You will need to go back to GitHub to create a pull request and merge it and close the
issue.
By using the Task feature in PyCharm you will have access to the issues for a project. You can
also easily create new branches based on them and follow a Git Flow type workflow if desired.
65
5. Source Control
Figure 512: Figure illustrating successful configuration with GitHub and tasks button appearing in upper
right.
Figure 513: Figure illustrating the Open Task window for creating a new branch for a GitHub issue.
66
5.7. Quick gist
Settings” and click on ”Generate new token”. After logging in, you should have the ability to create
a pull request. Fill in the appropriate information and click ”OK”.
You can also ”View Pull Requests”. When you run this command, PyCharm will show a ”GitHub
Pull Requests” tab along the bottom of the screen. It will list all of the pull requests on the project.
You can filter them, open them in GitHub, view the diff, or create a location branch from the pull
request. To run the ”Create New Local Branch...” action, right click on the pull request and select that
option.
5.8 Conclusion
In this chapter, we explored source control with PyCharm. PyCharm also has the notion of local
history in case we forget to check in code or aren’t using source control. We saw some examples
with the popular Git source control system.
67
5. Source Control
68
5.9. Commands
We specifically looked at the Git integration as well as GitHub integration. As soon as a project is
associated with source control, there will be a Git widget in the lower right and buttons to perform
common source control actions in the upper right. Using the Git widget we can switch branches
and perform other common branching operations. We can use task integration with GitHub to
create new branches based on issues and follow a Git Flow process.
5.9 Commands
• ”Update Project” - (command-t or ctrl-t)
• ”Show History”
• ”Highlight Words”
• ”Create Gist...”
5.10 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/3-source-control to try out Git in
PyCharm.
69
Chapter 6
Refactoring
71
6. Refactoring
Figure 61: Figure illustrating the Duplicate Tool Window on the bottom of PyCharm.
Having too many parameters can be confusing. It might be hard to remember what each
parameter is doing. It also might indicate that the function is doing too much, or the parameters
should be grouped together into their own configuration class. In modern Python, this could
be accomplished using Python 3.7’s Data Class feature. For older versions, namedtuples are an
alternative.
When you are thinking about refactoring keep your nose out for these code smells. They can
give you hints as to when you should change the nonfunctional aspects of your code. Refactoring
is an investment that can pay huge dividends in the future.
72
6.2. Finding Duplicate Code
Figure 62: Figure illustrating the context menu that appears when ”Refactor This” command is run.
are more than two duplicates, you can click on them to insert them into the difference view on the
right.
Below is a class hierarchy, where Wizard and Dragon are subclasses of Creature. Both of the
subclasses have the same method.
class Creature:
def __init__(self, name, level):
self.name = name
self.level = level
class Wizard(Creature):
def __repr__(self):
return f"Creature: {self.name} level: {self.level}"
class Dragon(Creature):
def __repr__(self):
return f"Creature: {self.name} level: {self.level}"
If you had a case similar to the following code, you might want to refactor the __repr__ method
into the base class of Creature. To do so, select the method you want to refactor. This refactoring
is called ”pulling up”, as we are moving a method from a subclass to a parent class. We would
select the __repr__ method in Wizard and the ”Refactor This” command (command-alt-shift-t or
shift-ctrl-alt-t) to bring up the refactoring popup. Select ”Pull Members Up...” to start the refactoring.
A window will appear and you can select the class you want to move the method to. In this
case select Creature. Hit ”Refactor” and your code should look like this:
class Creature:
def __init__(self, name, level):
self.name = name
self.level = level
73
6. Refactoring
Figure 63: Figure illustrating ”Pull members up to” window. You can select the methods you want to move
up and the class you want them to land in.
def __repr__(self):
return f"Creature: {self.name} level: {self.level}"
class Wizard(Creature):
pass
class Dragon(Creature):
def __repr__(self):
return f"Creature: {self.name} level: {self.level}"
Note that Dragon still has the __repr__ method. The easiest thing to do is delete it. PyCharm
is not quite confident enough to know that it should delete that as part of the refactoring. If you
74
6.3. Renaming items
re-run the find duplicates command after you’ve deleted Dragon’s __repr__ method, you should
see that this duplicate is now gone.
I wouldn’t be sure. However, if we rename compute to what it does more explicitly, you would
know right away and you could drop the comment:
shape.compute_bounding_box()
These renamings can be scary if you don’t catch all the uses. But that is not a problem with
automated refactoring.
Back to our D&D game: If you have a variable called player in an adventure game and you
wanted to change the name to hero, you could do this by doing a search and replace. That might
work, but if you had another variable named player_2 or a method called attack_player, those
could be erroneously renamed to hero_2 and attack_hero. Find and replace also might miss a
rename in a different file. Even if you matched exactly on player, perhaps it is a different symbol,
with the same name but from a different module.
The ”Rename...” command (shift-F6) will perform the rename in a safe manner. You can select
the variable you want to rename and run this command. If you don’t want to memorize all of the
hotkeys for refactoring, you can also access the refactoring commands from the ”Refactor This”
command.
When you are refactoring a variable, you type the new name and PyCharm will insert it in the
correct places.
If you want to rename a method, say replace the attack method with fight, highlight an
instance of the method (it can be an invocation or the method itself), and run the ”Rename...”
command on it. You can tell PyCharm to include renaming in comments and strings.
A ”Refactoring Preview” window will appear in the bottom. You can see where references were
found, and tell PyCharm to perform or cancel the refactor
You can also apply ”Rename...” to files. PyCharm will ensure sure that any file importing the
renamed file will be updated. Also, the VCS integration will allow you to easier track the file
rename. Of course if you realize you made a drastic mistake, you can always ”Undo” (ctrl-z or
command-z) and PyCharm will revert the changes as on unit (including filename changes).
The next time you want to rename something before you reach for find and replace, consider
using the safer, more intelligent ”Rename...” command.
75
6. Refactoring
Figure 65: Figure illustrating refactoring preview. Here you can see where the references were found before
approving the refactor.
76
6.5. Creating Constants
def get_defensive_roll(self):
return 3 * random.randint(1, 12) * self.level
The inlined literals are 3, 1, and 12. What does 3 mean. Presumably, the other numbers are
for randomly choosing a number between 1 and 12 inclusive (note that randint doesn’t follow
the half-open interval as range does, and includes the 12 as an option). These can be confusing to
colleagues who inspect the code later.
Another issue with debugging this code is that we can’t set a breakpoint and inspect the random
number itself. We can only set a breakpoint on the return statement and reverse engineer what
the random number was.
A refactoring to pull out the random number in its own variable is called ”Extract Variable...”
(command-alt-v or ctrl-alt-v). If you highlight the expression with the call to the randint function,
run the ”Extract Variable...” command, and name it as roll, your code will look like this:
def get_defensive_roll(self):
roll = random.randint(1, 12)
return 3 * roll * self.level
Following that refactoring, you could set a breakpoint in the method and inspect the value of
roll.
Note
There is also a ”Inline” (command-alt-n, or ctrl-alt-n) refactoring, which will take a variable and
inline its value. It is the opposite of Extract Variable.
The 3 number is a boosting modifier the defensive roll here. If we wanted to make this value a
configurable value we can use the command ”Extract Parameter...” (command-alt-p, or ctrl-alt-p).
You could select it and run the command with a parameter name of modifier to get:
def get_defensive_roll(self, modifier=3):
roll = random.randint(1, 12)
return modifier * roll * self.level
We have refactored our code to make it more clear about the intent. We have also added the
ability to change the modifier, but the default value is the same, so the behavior of the method
works with existing code. The method we looked at in this section is somewhat simple. However,
you can apply these same ideas to larger, more complex code as well.
77
6. Refactoring
If you wanted to reuse that banner in other places, you could copy and paste the code.
Alternatively, you can select the string and run the ”Extract Constant. If you rename it
PYTHON_TEXT you will get:
PYTHON_TEXT = ''' _ __ _ _| |_| |__ ___ _ __
| '_ \| | | | __| '_ \ / _ \| '_ \
| |_) | |_| | |_| | | | (_) | | | |
| .__/ \__, |\__|_| |_|\___/|_| |_| is cool!
|_| |___/'''
print(PYTHON_TEXT)
class Processor:
def process_data(self):
# compute stats
def main():
p = argparse.ArgumentParser()
p.add_argument('-f', '--file)
opts = p.parse_args()
if opts.file:
proc = Processor()
proc.process_data()
After selecting the main function and running the Move refactoring with a file named main.py,
your original file would look like this:
# process.py
class Processor:
def process_data(self):
# compute stats
def main():
p = argparse.ArgumentParser()
78
6.7. Summary
p.add_argument('-f', '--file)
opts = p.parse_args()
if opts.file:
proc = Processor()
proc.process_data()
This allows you to create dedicated modules that are specific to certain tasks. You can always
use the ability to run the code or execute tests (as we will see in a later chapter), to verify that the
code still works.
PyCharm also supports moving modules to packages and vice versa. A module is a file that
ends in .py. A package is a directory that has a file named __init__.py in it. If you had a module
that was growing large and you wanted to keep the namespace, you could refactor it into a package.
The implementation of the module would be placed in the __init__.py file, but you could add
other modules to it later.
6.7 Summary
We discussed many refactorings in this chapter. It was not a comprehensive discussion (as there
are whole books devoted to refactoring), but it should whet your appetite to improve your code.
Take advantage of the functionality in PyCharm to find duplicates in your code and clean them up
with refactoring. Another next step would be to research common code smells and the remedies
for them. PyCharm should make cleaning up your code much easier and also do it in a robust
manner.
6.8 Commands
• ”Locate Duplicates” - (Code -> ”Locate Duplicates...”)
• ”Rename...” - (shift-F6)
• ”Move” - (F6)
6.9 Exercises
1. Research Code Smells on Wikipedia. See if you can find any of them in your own code.
2. Research Refactorings. There are many books and articles that dive deep into this subject. See
if you can find places in your own code to apply them. PyCharm should make that easier.
79
6. Refactoring
3. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/4-refactoring to try out finding
some code smells and fixing them with PyCharm.
80
Chapter 7
Databases
7.1 Introduction
Many applications that create or read data use databases to make their lives easier. PyCharm has
great database support and can interact with most any SQL database.
Many companies even have dedicated roles to supporting and maintaining databases. This can
make developers feel that a database is someone else’s domain. Also, tools for using databases can
be hard, unfamiliar, or interrupt your flow. Also, most databases have different tools, so learning
each tool is a chore. Supporting and creating migrations as well as dealing with object relational
mismatches are pains.
PyCharm alleviates some of these issues. It has integrated database support. PyCharm also
uses the same UI across databases platforms. You only need to invest in learning a single tool.
Most of this chapter will focus on DataGrip, which comes with PyCharm Professional, but is
also a separate product.
conn = sqlite3.connect('runs.db')
with conn:
c = conn.cursor()
c.execute('CREATE TABLE Person(id INTEGER PRIMARY KEY, name TEXT)')
c.execute('CREATE TABLE Location(id INTEGER PRIMARY KEY, place TEXT)')
c.execute('''CREATE TABLE Run(id INTEGER PRIMARY KEY,
pid INTEGER,
lid INTEGER,
distance NUMBER,
FOREIGN KEY(pid) REFERENCES Person(id),
FOREIGN KEY(lid) REFERENCES Location(id)
81
7. Databases
Figure 71: Figure illustrating configuring a new Data Source for SQLite.
)
''')
c.execute("INSERT INTO Person VALUES(0, 'Matt')")
c.execute("INSERT INTO Location VALUES(0, 'Squaw Peak')")
c.execute("INSERT INTO Run VALUES(0, 0, 0, 52)")
c.execute("INSERT INTO Run VALUES(1, 0, 0, 50)")
If you run this from PyCharm, it should execute without issue. This code creates a file, runs.db,
on the filesystem in your working directory (often next to the dbexample.py file). To get your
project to recognize it as a datasource, right-click on the project in the Project view and select ”New”
-> ”Data Source”. It will ask for the ”Path” to the data source, which you can point to the location
of runs.db. At that point, the ”Driver” option should be filled in with ”Sqlite (Xerial)”. If you hit
”OK”, a new window pops up to configure the data source.
The settings on the configure window should be fine. However, if you see a red font by the
driver file that will be an indication that you need to download the driver. Click on the blue
”Download” link, and PyCharm will handle the rest. At this point hit ”OK” and you will notice
on the far right of the editor is a ”Database” tab.
The Database view has a tree view with the name of the datasource, runs.db in our case. If you
expand schemas and main, you will see all of the tables we have created: Location, Person, and
Run. If you expand one of those tables you will see the columns with their corresponding types
82
7.3. Database Diagrams
Figure 72: Figure illustrating datasource view. Note that you can expand it to view column types.
and any keys or indexes that were defined. There are icons on the column names to indicate if they
are a key (if we had an index, there is also an icon for that).
The nice thing about this view is that it will work with any data source. Once you have the
muscle memory, you can use a different database and it should feel the same.
Tip
You can also drag and drop a sqlite file onto the database tab and PyCharm will configure it
for you!
83
7. Databases
Figure 73: Figure illustrating the result of the ”Show Visualization” command.
you want to include in the data source view, and then show the visualization, which will be limited
to the tables selected.
Although DataGrip has code completion, if you started writing SELECT l. and were waiting
for assistance, you would be waiting for a long time. In that case, DataGrip doesn’t know what
the alias l refers to. Even if you typed out SELECT Run., DataGrip would not pull up the options
selecting the columns of the Run table. A hack to trick DataGrip is to first say SELECT * FROM Run
as r. At this point, DataGrip will know what r is aliased to, and will give you column completion
on that name.
If you ”Execute” (command-enter, or ctrl-enter) the query a data grid will appear with the
results. The data grid that displays the results is live. So you can sort the table by clicking on
the column headers. If you wanted to sort by distance, you could click on that column.
84
7.5. Modifying Schemas
If you view a table directly (by double-clicking it on the data source view, or doing a SELECT *
FROM Runs) you can also edit the data. You can double click on a field to change its value. After
you change the value, it isn’t automatically pushed back to the database. You need to run the
”Submit” command (hitting the button with a green arrow pointing to the DB, or command-enter,
or ctrl-enter).
You result view also has the ability to export the results as a TSV, CSV, JSON, or the clipboard.
In addition, you can view the DDL for a table. This can be useful if you didn’t create the table or
don’t have the code that created it. You can use the DDL and a dump of the data to make a local
copy for your own purposes.
85
7. Databases
Figure 75: Figure illustrating different options for modifying parts of a table. You can add and remove
columns. You can also change attributes of columns.
PyCharm will treat it as a normal string. You can click on the bulb and inject a language or type
a little more SQL. Then PyCharm converts the string to SQL automatically. Once I have typed:
86
7.7. Summary
Figure 76: Figure illustrating typing SQL in a string. When you start typing it is treated as a normal string.
If you want to hint to PyCharm that it contains SQL, you can click on the bulb and do a language injection.
Figure 77: Figure illustrating that PyCharm will automatically inject a SQL language and give us code
completion if we have a data source configured and type enough SQL.
PyCharm pulls up code completion options for you. It will complete table names, column
names that are unique to your schema. When you modify the schema, PyCharm modifies the
symbols in the language injected SQL strings in Python. As we can see, PyCharm’s understanding
of symbols gives it great power. You can even by navigate symbols as well. There are many other
languages you can inject, but SQL completion is a really nice feature of PyCharm.
7.7 Summary
In this chapter we looked at the DataGrip tooling integrated into PyCharm. This is a powerful end
to end suite of tools for interacting with most SQL databases. One of the advantages of DataGrip
is that once you learn the tool you can use it with any other supported database. We also discussed
language injection. This feature gives us code completion inside of native Python strings. The
database tools in the professional version of PyCharm are a compelling reason to choose that
platform.
7.8 Commands
• ”Show Visualization” - (right click on the data source ”Diagrams” -> ”Show Visualization”,
command-shift-alt-u, or ctrl-alt-shift-u)
87
7. Databases
• ”Submit” - (hitting the button with a green arrow pointing at the DB, or command-enter, or
ctrl-enter).
7.9 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/5-databases to try out opening an
existing database with DataGrip.
88
Chapter 8
89
8. Server-side Python Web Applications
new virtual environment. In the ”More Settings” area at the bottom of the window, you will see
options for ”Scaffold:”, ”Template language:”, and ”Templates folder:”. The scaffold is the internal
project layout of the Pyramid project. The default value of ”starter” is fine. In this chapter we will
use the ”Chameleon” template language instead of the default value of ”Jinja2”. Hit the ”Create”
button and PyCharm will generate a project for you.
After creating the project, PyCharm may generate some warnings about missing packages
and the project not be installed for development. You can view what PyCharm installed for
you by clicking on Terminal in the bottom and running pip list. We will want to install these
dependencies, so click on ”Install requirements”.
You will also need to run python setup.py develop. This command installs our project
as an editable package. The project source code will be found during imports from our virtual
environment, but if we change any code, we won’t need to reinstall it. We can do that from the
terminal, click on ”Run setup.py develop”, or select ”Tools” -> ”Run setup.py Task...” and choose
”develop”.
At this point you click on ”Run (WebDemo)” (shift-F10). A ”Run” console will appear in the
bottom of PyCharm with a link to the development server. Click on the link to view your web
project. If you see an error page, you will need to open webdemo/templates/layout.pt and
replace WebDemo: with webdemo:.
90
8.2. Creating Server-side Projects
Figure 82: Figure illustrating the generated project. Note that PyCharm has generated some warnings.
Figure 83: Figure illustrating error if static calls are pointing to WebDemo: instead of webdemo:.
91
8. Server-side Python Web Applications
Tip
Once you have the runner working for your webpage, you should make one more change. If
you try to run it again you will get an error complaining that the ”Address already in use”.
This is because the port that the web application is using is not available. A small change can
address that.
Tweak the run configuration by running ”Edit Configurations...”. Then select the ”Single
instance only” checkbox. This insures that if you hit run again, PyCharm will kill the prior
version and you won’t see this error.
Pyramid routes views to renderers. In webdemo/views.py you will see this code:
@view_config(route_name='home',
renderer="templates/mytemplate.pt")
def my_view(request):
return {'project': 'WebDemo'}
This code says this view has the name of home, uses the templates/mytemplate.pt template,
and returns a dictionary of data.
In webdemo/__init__.py there is some code that maps the home name to the route of /. The
line looks like this:
config.add_route('home', '/')
This routing abstraction might seem confusing, but it can be powerful. To validate that the web
application is dynamic, update the return value of my_view to add a name:
@view_config(route_name='home',
renderer="templates/mytemplate.pt")
def my_view(request):
return {'project': 'WebDemo',
'name': 'Matt'}
92
8.2. Creating Server-side Projects
Figure 85: Figure illustrating the view. Note the icon with the H in the left gutter. If you click it, you will be
taken to the template.
You will see on the left of the view in the gutter is an icon with an H under it. If you click it, it will
take you to the template for that view. Now change the template (templates/mytemplate.pt).
There is a line that looks like this:
<p class="lead">Welcome to <span class="font-normal">WebDemo</span>
Reloading the webpage will show you that the template is using the data provided from the
view.
93
8. Server-side Python Web Applications
Note
If you don’t want to restart Pyramid all the time, you can add --reload as an ”Additional
options:” flag in the ”Run Configurations”. This is specific to Pyramid, but other frameworks
have similar functionality. You might need to start Watchman in a terminal (watchman -f) or
install Watchdog (pip install watchdog).
This tweak makes development easy. You change some code, and the server notices it, and
restarts.
Go back the mytemplate.pt and delete the content inside of the <div class="content"> tag.
Add the following content to show flag indicating whether we are showing odd numbers. Because
we are using Chameleon, we will be using TAL (template attribute language) to do that. Other
templating language have different syntaxes but the same ideas apply:
<h1>Template Demo</h1>
<h2 tal:condition="show_odd">Showing odd numbers as well</h2>
<ul>
<li tal:repeat="n data">Num ${n}</li>
</ul>
A few things to note. PyCharm will automatically close HTML tags for you. PyCharm also
takes care of code completion with TAL attributes. Sadly, PyCharm does not complete the context
variables (data), but it does know about n.
If you change the value for the 'show_odd' key in my_view to False, the webpage will not
filter out the odd values. To hide those, you need to change the template code a little. TAL has a
tal:condition attribute that can turn tags on or off, but you can’t apply it to the <li> tag because
we are looping with it. To remedy that, you can change the <li> tag to a <div> tag (highlight li
and type div), and then add a new inner <li> tag:
<h1>Template Demo</h1>
<h2 tal:condition="show_odd">Showing odd</h2>
<ul>
<div tal:repeat="n data" tal:omit-tag="True">
<li tal:condition="n%2 == 0 or show_odd">
Num ${n}
</li>
</div>
</ul>
If you take advantage of PyCharm’s smarts around editing HTML, this change is rather
painless.
94
8.4. Emmet
Figure 87: Figure illustrating HTML tag hierarchy at bottom of editor. Click the colored elements in the
bottom bar.
Another thing to note is that PyCharm tracks the hierarchy of tags where the cursor is at the
bottom of the editor. These tags are clickable if you want to use them to navigate. In the figure
below, you’ll see div > div > div.content > ul > div > li. Each of these can be clicked to
quickly navigate through the DOM hierarchy without losing your place.
8.4 Emmet
PyCharm ships with Emmet integration. Previously known as Zen Coding, Emmet allows you
to create HTML from CSS. At the most basic level, you can create single elements. To create the
<div></div> tag, type div in the template editor and hit TAB.
If you wanted to make a <div class="blue" id="header"></div> tag, type:
div.blue#header
95
8. Server-side Python Web Applications
There is an option to have a pop-up window with a preview of the abbreviate before expanding
it. Go to preferences and search for ”emmet” and click on ”Enable abbreviation preview”.
This command requires node to be installed npm in your system path. Now in layout.pt, go
to the line with:
<link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/
bootstrap.min.css" rel="stylesheet">
Change the href value to /static/ and you will see that you have directory completion
because the root directory was marked as a resource root. Finish filling it out with the new path to
bootstrap:
/static/css/node_modules/bootstrap/dist/css/bootstrap.css
At this point, PyCharm will recognize and parse the CSS and it will be available for code
completion. Note that if our project references content hosted on CDN’s (that aren’t in a resource
root), PyCharm won’t use them for code completion. Also, any symbols PyCharm finds in static
files (JavaScript functions, CSS class names) are ”symbols” in the PyCharm sense. So we can
leverage that for navigation, code completion, refactoring, etc!
96
8.6. Other Tools
Figure 89: Figure illustrating code completion after we have added a local copy of bootstrap in a resource
root.
Figure 810: Figure illustrating various options for running tools before launching a web application.
8.7 Summary
In this chapter, we explored PyCharm’s support for server-side development. PyCharm has many
frameworks supported out of the box. Sometimes we need to provide some extra hints to PyCharm
so it knows how to handle certain files. Once we do, we can reap the benefits of code completion.
PyCharm also enables us to quickly create HTML code with the Emmet integration.
8.8 Commands
• ”Run (WebDemo)” - (shift-F10)
• ”Edit Configurations...”
97
8. Server-side Python Web Applications
8.9 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/6-web-applications to try out creat-
ing a basic Pyramid application.
98
Chapter 9
9.1 Introduction
One of the key benefits of PyCharm is that it understands a whole project. In addition to Python,
there strong support for JavaScript and web development. If you are working on a web application
with JavaScript on the frontend, PyCharm has you covered. It understands frameworks like
Angular, React, and Vue. It also integrates with TypeScript, LESS, and SASS. Finally, PyCharm
can help with using ElectronJS to create desktop applications. In this chapter, we will be exploring
these features of PyCharm.
In the js folder create a site.js JavaScript file. Add the following contents to it:
function runAtLoad() {
person = "Paul"
runAtLoad()
99
9. Client-side Web Applications
Figure 91: Figure illustrating the browser icons in the upper right of an HTML page.
100
9.2. Basic HTML and JavaScript
Figure 93: Figure illustrating that PyCharm will offer an intention to fix a variable lacking a scope
declaration.
If you click on the Chrome icon on the HTML page, you should see a web page that says
”Welcome to JS Demo”. If you open the JavaScript Console (View -> Developer -> ”JavaScript
Console”), you should see the text Nice to meet you Paul.
The code appears to have run, but there is an issue. The person variable doesn’t have a scope
declaration. Unlike Python where variables are local to the scope they are defined in, JavaScript
would prefer that you are more explicit when defining the scope.
The default scope in JavaScript for a variable is global scope. That’s what’s happening with our
person string variable. Global variables tend to cause problems as they remove encapsulation and
can be changed anywhere in the code. It is best to avoid them unless you explicitly need them. You
will see that PyCharm underlines the person variable and gives you a code intention to address
this.
If you click on the intention, it will change the line to:
let person = "Paul"
With the let scope declaration included, the person variable is no longer global. From the
JavaScript console, you can try and access the person variable and it is no longer possible.
PyCharm has refactoring support for JavaScript. Highlight the code "Nice to meet you "
+ person and run the ”Extract Method” command (command-alt-m, or ctrl-alt-m). You will be
presented with the option to refactor to a global scope or inside of runAtLoad. Select refactor to
global scope. Your code will look like this:
function getMessage(person) {
return "Nice to meet you " + person;
}
function runAtLoad() {
let person = "Paul"
console.log(getMessage(person))
}
runAtLoad()
101
9. Client-side Web Applications
Figure 94: Figure illustrating creating a TypeScript file. Note the dialog to compile this file to JavaScript
along the top.
We can also refactor to another file. Select the getMessage function and run the ”Move”
command (F6). Tell PyCharm to move it to a file, js/home.js. PyCharm will create a new file
for you with the refactored content.
Note
Some of the refactorings, such as moving code to another file require ECMAScript 6 features.
Browser support for such features is continuously improving.
The file editor should have a dialog appear along the top asking if you want to compile this
file to JavaScript. If you click yes in the project explorer, the file will become expandable. When
you click on the file you will see the compiled JavaScript file appear. In this case it will be called
app.js.
Your JavaScript files can take advantage of TypeScript code. In the site.js file, you can update
it to use the new person code:
102
9.4. Using Angular
Figure 95: Figure illustrating the compiled JavaScript that is derived from the TypeScript.
function runAtLoad() {
let person = new Person('Paul', 64)
console.log(getMessage(person.name))
}
103
9. Client-side Web Applications
Figure 96: Figure illustrating the run buttons in the gutter of the package.json file.
Figure 97: Figure illustrating the ”Run Configuration” generated by clicking on ”start” in the package.json
file.
104
9.5. Less
9.5 Less
When it comes to CSS, sometimes less is more. In the case of Less21 , a language that allows us to
create variables, mixins, and functions with CSS, less is definitely more.
Let’s assume you have a webproject and you want to take advantage of Less. Using PyCharm,
add a new file to the css directory that ends with .less. From the New menu there are options for
various types of files, but there is no option for a Less file. That’s ok, create a new file, app.less,
and change the extension to .less.
When you open the file, PyCharm will present a dialog along the top that asks if you want to
enable a file watcher. The file watcher will monitor the Less file and any time it changes, it will
regenerate the CSS file that it creates. Click ”Yes” to enable the file watcher. There will be various
options, but generally the defaults will work fine.
Let’s add a variable @color1 that stores a green color. Insert the following RGB hexadecimal
values into the Less file:
@green: #00ff00
In the gutter next to the variable a green button will appear. If you click it, it will open a color
chooser window. From there you can customize the color if you prefer.
Note
If the filewatcher is not generating CSS, it could be because the executable is not found on your
machine. If npm is installed on your machine you can run:
21
https://lesscss.org/
105
9. Client-side Web Applications
Figure 99: Figure illustrating the option to tell PyCharm to compile Less to CSS.
Figure 910: Figure illustrating the color picker dialog in PyCharm. You can click in the gutter next to the less
variable to open it.
106
9.5. Less
$ npm install -g less
h1 {
color: @green;
background-color: @page-color;
&:hover {
color: @lite-green;
}
}
h2 {
color: @green;
}
In this case, the CSS does contain fewer lines of code so the advantage of Less is not immediately
obvious. But, as we add other styling widgets, we probably will want to reuse colors, like we are
reusing @green. By using Less variables, we can change the color in one place and not have to
worry about doing a search and replace.
Go to the index.html page and update it to refer to the CSS file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<h1>Welcome to JS (& CSS) Demo</h1>
</body>
</html>
107
9. Client-side Web Applications
Figure 911: Figure illustrating HTML code rendering CSS generated from Less.
If you click on the browser icon, you will see a basic demo. If you hover over the h1 tag, you
will notice that the color changes.
Less is a powerful tool for managing and factoring CSS. If you are working on a project, it is
a great way to control styling. PyCharm will let you create and manage CSS and Less from the
editor, including code completion. Take advantage of this tooling.
9.6 Electron JS
To wrap up this chapter about JavaScript let’s introduce Electron JS. This framework allows you
to create GUI applications using JavaScript. It bundles the Chrome browser and Node into an
executable. Notable examples of applications built upon ElectronJS include Slack, the Atom editor,
VS Code, and Postman. Electron runs on multiple platforms and allows you to create desktop
applications using the technologies you use for the web. This section will explore the PyCharm
support for working with Electron JS.
Installing Electron JS is straightforward if you have Git and NPM installed. Let’s try a simple
app. Run the following:
$ git clone https://github.com/electron/electron-quick-start
$ cd electron-quick-start
$ npm install & npm start
These commands will launch a simple application. You should note that this is not a web
browser, it is a stand-alone application. Let’s go and explore PyCharm’s support for managing
Electron JS code.
Use PyCharm to create a new project from the electron-quick-start directory. Sadly,
Electron JS uses JavaScript (Node) instead of Python. You will want to make sure that you have
108
9.6. Electron JS
Figure 912: Figure illustrating a simple Electron JS application. Note this is not a web browser as you can
see it has its own menu.
the Node plugin installed to work with the code in this project. Open up ”Preferences” and click on
”Plugins” on the left. Inside of the Plugins screen there is a search area. Type ”NodeJS” in there to
see if the plugin is installed. If the plugin is not there click on the ”Browse Repositories...” button
and search for a plugin named ”NodeJS”. Highlight that plugin and click on the ”Install” button.
After installing the plugin you will need to restart PyCharm.
We can add a Configuration to ... the Electron application. Click on the ”Add Configuration...”
button (or click on the ”Run” -> ”Edit Configurations...” menu). From the ”Run/Debug
Configurations” window click the plus button to add a configuration. There should be an option
for ”Node.js”. You can change the ”Name:” field to ”Electron” and change the ”Node interpreter:”
value to the electron interpreter. You will find this inside of the node_moudles/.bin/ directory.
109
9. Client-side Web Applications
Figure 914: Figure illustrating configuring the interpreter for Electron JS.
The ”Working directory:” should have the project directory (electron-quick-start). Leave the
”JavaScript file:” blank and set ”Application parameters:” to . (a single period). This tells Electron
to run the application in the working directory.
If you run the configuration, the Electron JS application should appear. At this point you should
be able to edit index.html. You can change the <h1> tag to:
<h1>Hello World from PyCharm!</h1>
If you reload the Electron JS application (View -> Reload) it will show the updated content. You
don’t even need to stop and restart the application.
9.7 Summary
PyCharm is a powerful editing tool. However it can require some configuration. In this chapter,
we walked through how to configure PyCharm so it will run an Electron JS application as
well as demonstrated its deep integration with the JavaScript language and common JavaScript
frameworks.
9.8 Commands
• ”Extract Method” - (command-alt-m, or ctrl-alt-m)
• ”Move” - (F6)
110
9.9. Exercises
9.9 Exercises
1. Create a project that uses Angular. Take advantage of the Angular support in PyCharm.
2. Create a project that uses TypeScript. Take advantage of the TypeScript support in PyCharm.
111
Chapter 10
Debugging is a common activity for developers. Often times developers will result to using print
functions to debug their code. Some will use a command line debugger like the pdb module,
but few editors have the ability to debug and inspect code in the editing environment. PyCharm
includes a very powerful debugging environment that is sure to make tracking down bugs faster
and easier.
To quickly create a configuration, you can right-click on the file and click on the ”Run” or
”Debug” command. This will create a basic Python configuration and run or debug the module.
Let’s add a breakpoint by clicking in the gutter left of the line of code. Add a breakpoint where
result is assigned to a list and then debug the program.
When you debug a program with a breakpoint, the execution should stop at the breakpoint. In
addition a ”Debug” window will appear. Down the left side of the Debug window are buttons for
”Rerun” (control-F5), ”Resume” (F9), ”Pause”, and ”Stop” (command-F2). Below those are buttons
for ”View Breakpoints” (command-shift-F8 or ...) and ”Mute Breakpoints”. Along the top are buttons
for ”Show Execution Point” (alt-F10), ”Step Over” (F8), ”Step In” (F7), ”Step In (My Code)” (alt-shift-
F7), ”Force Step Into” (alt-shift-F7), ”Step Out” (shift-F8), ”Run Cursor To” (alt-F9), and ”Evaluate
Expression” (command-F8 or ...)
The ”Rerun” command will restart your debugging session. ”Resume” is for continuing after
you have paused or hit a breakpoint. The ”Pause” command will stop execution. Normally we
113
10. Debugging Python applications
Figure 101: Figure illustrating a breakpoint in the gutter and the debugger window.
set a breakpoint to stop execution and inspect variables. But sometimes you have a long-running
program and you don’t know where to set the breakpoint. The pause command can help you figure
out where execution is getting stuck or what your program is up to. The ”Stop” command halts
the current program.
The ”View Breakpoints” command may seem simple. It will show all the locations where
breakpoints are set. But you can also toggle breakpoints, log when they are hit, and set a condition
to enable them with this command. For example, you can add a breakpoint to the print(result)
line and tell it to only stop when 'Fido' in results. From looking at the code, it would appear
that 'Fido' should be removed from result. But the conditional breakpoint will be hit. You can
also log when breakpoints are hit and disable them after the first time they are hit. These are nice
options that can really help when debugging a problem with code.
The ”Show Execution Point” command brings your cursor back to the last line that was
executed. This is useful if you are jumping around looking at other files and decide you want
to quickly navigate back to the execution point. The ”Step Over” command executes until the next
line of code. ”Step In” will step into a callable (a function or method). While ”Step In (My Code)”
will jump into your code, but not third-party or standard library code. PyCharm allows you to
configure skipping over certain sections of code and step into will ignore those. If you really want
to jump into them use the ”Force Step Into” command. There is also another option, ”Smart Step
Into” (shift-F7), which doesn’t have a button for it. If you have a line with several methods on it,
run this command and you can choose the method you want to step into. ”Step Out” hops out of
114
10.1. Debug Tools
the current method or function. ”Run Cursor To” will allow you to resume execution to the line
the cursor is on. ”Evaluate Expression” lets you type in a Python expression much like the REPL.
If you are debugging this program step into the remove_pet function. You will see that
PyCharm has inline debugging and shows the values of the variables next to the line where they
are set or changed. The inline debugging values are color-coded. They are green if they haven’t
changed and change to orange when they are updated or change.
In the Debug window, there are two tabs, ”Debugger” and ”Console”. In the Debugger tab, you
can see the stack in the ”Frames” section and the objects in the ”Variables” section. The variables
section shows the values of the variables. But, it also lets us interact with the variables. There is
a ”Set Value...” command (F2) that let’s you override a variable. You can navigate to where the
variable was created with ”Jump to Source” (F4).
PyCharm has the notion of watches. Watches are special variables that exist inside a function or
method. Typically you would set a watch to an expression. In the case of our code, we could create
a watch using ”New Watch” with the value of 'Fido' in result. PyCharm would show this as a
boolean and its value would dynamically change if the result variable ever had 'Fido' in it.
There is also the Console tab in the Debugger window which shows any output to standard out
and also allows you to enter input to standard input.
If you step through the loop in remove_pet you will see that the code only removes the first
'Fido'. This is due to the iteration behavior of Python. While iterating over a list, Python keeps
track of the index of iteration. If you remove something at the current index, all the other items
are shifted to the left. Hence, when we remove the first 'Fido', the second 'Fido' shifts into its
place, but then the iteration moves onto the next item, which is now 'Pluto'. One solution to
this situation is to loop over a shallow copy of the list using a slice construct and then update the
original list.
115
10. Debugging Python applications
Figure 103: Figure illustrating debugging. Note that we have stepped into remove_pet and the value for
kennel and other are shown inline.
Another option would be to use a pure function and not mutate the list that was passed in but
rather return a new list:
def remove_pet(kennel, name):
result = []
for other in kennel:
if name != other:
result.append(other)
return result
116
10.2. Summary
10.2 Summary
This section provided an overview of the tools for stepping through code and setting breakpoints.
These powerful tools are a great way to debug and understand code. Python is a dynamic
language, getting used to tools like the REPL, watches, and conditional breakpoints can simplify
and accelerate reading, writing, and debugging code.
10.3 Commands
• ”Debug” - (command-alt-F9).
• ”Rerun” - (control-F5)
• ”Resume” - (F9)
• ”Pause”
• ”Stop” (command-F2)
• ”Mute Breakpoints”
• ”New Watch”
117
10. Debugging Python applications
10.4 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/7-debugging to try out creating break-
points.
118
Chapter 11
Packages
One of the main draws to Python is the extensive third-party libraries available. The Python
Package Index [#] has over 160,000 packages and is growing bigger every day. When you need
to perform a new task with Python, you should check if one of the available packages provides
that functionality. If oner doesn’t exist, you might want to build your own packages. PyCharm has
support for both.
Use PyCharm to create a new project with that directory in the ”Location:” field. Expand the
”Project Interpreter” dropdown and select ”New environment using Virtualenv”.
If you open the setup.py file you may notice that it says ”No Python interpreter configured for
the project” along the top. If that is the case, point the project interpreter to the virtual environment.
After than you should see PyCharm complaining about missing package requirements. Click on
”Install requirements”.
Let’s make a simple change to the requests/__init__.py file. We will add a print function
to show that the file has been changed. Below the docstring in that file enter the line:
print("THIS IS OUR CUSTOM VERSION")
At this point if you tried to use the Requests library from the virtual environment, Python
would complain with a ModuleNotFoundError (unless you have it installed in your system library).
Even though you created a virtual environment and installed the dependencies for Requests, the
Requests library hasn’t been installed.
What you want to do is install Requests in development mode. This installs it into the virtual
environment and also allows you to edit the local copy of the requests package. Any edits will
22
https://pypi.org
119
11. Packages
Figure 111: Figure illustrating create a new project with a new virtual environment.
120
11.1. Working with Existing Packages
Figure 113: Figure illustrating setup.py file not having an interpreter associated with it.
Figure 114: Figure illustrating adding a custom line of code to the Requests project.
121
11. Packages
be reflected immediately in the virtual environment. You can do this from the command line by
entering the virtual environment and typing:
$ python setup.py develop
Because this is a PyCharm book, let’s do it from PyCharm. Click on ”Tools” -> ”Run setup.py
Task...”. Click on ”develop”.
At this point, when you load the Requests library from your virtual environment, you should
have access to the version you are working on. As you make changes to the library you will be
able to get these changes as well.
The output from using the new library should look like this:
>>> import requests
THIS IS OUR CUSTOM VERSION
122
11.2. Creating New Libraries
From the new popup select ”Python Package”, and enter ”calculator” for the package name (PEP
8 suggests that we name packages in lowercase). If you expand the new package folder you will
see that PyCharm created a __init__.py file for you. Open that file and add the following code:
class Calculator:
If you open the ”Python Console” you will have access to the calculator package. You can
run the following code:
>>> import calculator
>>> calc = calculator.Calculator()
>>> calc.add(2, 5)
7
If we want to share the calculator package so other code can take advantage of it, we have
a few options. We can copy the package into the code where we need it. We can also update the
PYTHONPATH environment variable to point to the directory where calculator resides. The former
is not recommended as copying code in general is something to be weary of. If you have bugs to
fix or features to add, you have to do it in more than one place. The latter is also not recommended
as editing the environment variable for each package is tedious. A better option is to create a
proper Python library and use the standard Python tools (virtual environment and pip) to install
the library.
Let’s walk through the necessary steps to convert this code into a reusable library. We are
missing a setup.py file, so let’s create one. This is a file that is rarely created and the format is
a little convoluted. Because this file is typically created once you don’t deal with them much. Also,
the setup.py file can be confusing. It is the entrypoint to register and upload to PyPI. It indicates
what the package metadata is: who is the author, the version, license, homepage, etc. It controls
how source tarballs, binary, and wheel files are created. It specifies which files (both code and data)
files belong in a distribution. It also instructs Python on how to install a package. It can specify
dependencies as well as console executables that should be installed. In addition it can specify test
suites and a test runner.
PyCharm has a command that will help stub out a setup.py file. Run the ”Tools” -> ”Create
setup.py” command. This will bring up a popup where you can provide data about the project. Put
in a version number (0.1.0 is a good starting point), url, license, author, email, and description.
After you run the command you will have a setup.py file that looks like this:
from setuptools import setup
setup(
name='Calculator',
version='0.1.0',
packages=['calculator'],
url='https://calculat.or',
license='MIT',
author='Matt Harrison',
author_email='[email protected]',
description='A Pythonic calculator'
)
123
11. Packages
Figure 116: Figure illustrating filling in the ”Create setup.py” command window options.
In our case, the important part of this file is that the packages parameter is set to a list with
the name of our package in it. This parameter indicates which folders will be bundled up in this
library.
At this point we could register this project on PyPI, create a source distribution, and upload
to PyPI. Since this is a silly example, I wouldn’t do that, but the command would be python
setup.py register sdist upload. (In addition the ”Calculator” name is already used on PyPI
so uploading would fail). If the name had not been taken we could install the package with pip
install Calculator.
If you wanted to use this library in another project you were working on, you could go through
the uploading to PyPI process and use pip to install. Sometimes you might want to skip using PyPI.
Here are two options for installing packages without uploading to PyPI. If you wanted to update
the Calculator code while working on your new project, a better option is to run pip install -e
. using the project virtual environment from inside of the Calculator directory. If you don’t need
to edit Calculator, you can run pip install ..
11.3 Summary
In this chapter we discussed editing existing packages from existing code and starting a new
Python package from scratch. We explored how we can set up our environment to use packages in
development mode. We also looked at creating a new library from scratch. We can use PyCharm
to stub out the contents of the setup.py file for us. Once we have that file, we can upload to PyPI
or install our library locally bypassing PyPI.
124
11.4. Exercises
11.4 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/8-python-packages to create a
project.
125
Chapter 12
127
12. Performance and Profiling
* get corpus
* score = (count positive - count negative) / (num words)
bounds [-1, 1]
"""
import os
import re
import time
import urllib
import requests
BASE = 'https://raw.githubusercontent.com/jeffreybreen/'\
'twitter-sentiment-analysis-tutorial-201107/master/'\
'data/opinion-lexicon-English/'
NEG_URL = f'{BASE}negative-words.txt'
POS_URL = f'{BASE}positive-words.txt'
STOPWORDS_URL = 'https://raw.githubusercontent.com/'\
'stanfordnlp/CoreNLP/master/data/edu/stanford/nlp/'\
'patterns/surface/stopwords.txt'
def get_line_words(fin):
r"""
>>> get_line_words([': ."hello world, my name!\n', 'is matt.\n'])
['world', 'my', 'name', 'is', 'matt']
"""
book_words = []
word_re = re.compile(r'(\w*)')
def get_posts(query):
enc = urllib.parse.urlencode({'q': query})
url = f'http://search.talkpython.fm/api/search?{enc}'
res = requests.get(url)
return [d for d in res.json().get('results')]
def get_score(words):
if not len(words):
128
12.2. Profiling an Application
return 0.0
pcount = 0
ncount = 0
remove = 0
for word in words:
if word in stop:
remove += 1
continue
if word in pos:
pcount += 1
if word in neg:
ncount += 1
def main():
get_url(NEG_URL, 'neg.txt')
get_url(POS_URL, 'pos.txt')
get_url(STOPWORDS_URL, 'stop.txt')
posts = get_posts('numpy')
if __name__ == '__main__':
start = time.time()
main()
print(f"\ntook {time.time() - start:.3} seconds")
Note that this application uses the third-party Requests library. You will need to install that
into your active virtual environment to run the code.
Create a run configuration and execute the file. The output will print out the title and the score
of the description. On my machine (2015 MacBook) it prints:
Python in Finance Score: -0.045
Serverless software Score: 0.000
...
PyPy - The JIT Compi Score: -0.034
Effective Python Score: 0.000
Python in Brain Rese Score: 0.093
took 2.04 seconds
The report states that it takes almost two seconds to run. Let’s use the profiling capabilities of
PyCharm to figure out where our time is being spent.
129
12. Performance and Profiling
130
12.3. Capturing Profile Information
Figure 123: Figure illustrating right-clicking on the function to get to the graph.
which has arrows indicating which functions call other functions. From the ”Statistics” tab, we
can right-click on a function and select ”Show on Call Graph” to view the function in the graph.
It turns out that the main function calls get_score which uses two list comprehensions for the
majority of its work. The rest of get_score takes 27% of the time. This code is CPU bound, so it is
possible that we can speed it up. Common ways to speed up code are parallelizing it (running on
multiple CPUs), using a smarter algorithm, or caching.
If we look around in the graph we will see that there is also some I/O-bound code. The calls to
get_url and get_posts fetch data over the network. This code is I/O-bound, we are waiting for
the network to return the results of the page. In order to speed this up, we would need to migrate
to asynchronous code, use threading to batch up the waiting, or use caching.
131
12. Performance and Profiling
Note
If you have yappi installed, PyCharm will use that to profile. By default, PyCharm uses
the cProfile library found in the standard library. Yappi has per-thread debug information,
profiling decorators, and other features.
132
12.4. Addressing CPU Bound Code
pcount = 0
ncount = 0
remove = 0
for word in words:
if word in stop:
remove += 1
continue
if word in pos:
pcount += 1
if word in neg:
ncount += 1
On my machine, the runtime goes from 2 seconds to 1.4 seconds. A 30% improvement, by
changing 6 characters. That’s a powerful insight gained from the tooling. But we can do better
still.
Rerunning the profiling again, we see that the most time is now spent on the set
comprehensions. In fact, the neg, pos, and stop sets are repeatedly created. When we find that we
are doing the same thing multiple times, that is an indication that we should cache the results (and
only calculate them one time).
Let’s do one more refactor to both main and get_score. We will calculate the sets in the main
function and then pass them into the get_score function:
def get_score(words, neg, pos, stop):
if not len(words):
return 0.0
pcount = 0
ncount = 0
remove = 0
for word in words:
if word in stop:
remove += 1
continue
if word in pos:
pcount += 1
if word in neg:
ncount += 1
def main():
get_url(NEG_URL, 'neg.txt')
get_url(POS_URL, 'pos.txt')
get_url(STOPWORDS_URL, 'stop.txt')
posts = get_posts('numpy')
133
12. Performance and Profiling
pos = {line.lower().strip() for line in open('pos.txt')}
stop = {line.lower().strip() for line in open('stop.txt')}
12.5 Summary
This chapter took a simple application and optimized its runtime performance. We used the
PyCharm profiling functionality to quickly view what code is taking the most time. Using the call
graph, we were able to see where the code was called. By using the proper data structures and some
caching we reduced runtime by 78%. Profiling is not unique to PyCharm, but its tight integration
allows you to profile from the same application, quickly, without losing focus and having to juggle
between tools. This is a huge benefit for developer productivity.
12.6 Commands
• ”Profile ’program’” - Click on button with clock
12.7 Exercises
1. If you want to try your hand at profiling, you can get the original version of the sentiment
application covered in this chapter at https://github.com/talkpython/mastering-pycharm-
course/tree/master/extra_samples/profiling/
Try running the profiler on this project and see if you can identify the same issues as we have.
See what other performance improvements you might make.
2. Open a recent project and execute it under the profiler. What is taking the most time?
134
Chapter 13
Unit testing
Because we will be using the pytest library, we named our test file test_parser.py. The pytest
library recognizes files that start will test_ or end in _test.py as test files. We will follow that
convention.
Open up test_parser.py and create a test. The easiest way to make a pytest test is to create a
function that starts with test and use the assert statement in it. Here is a basic test:
from numparser import parse
def test_basic():
135
13. Unit testing
Figure 131: Figure illustrating changing the ”Default test runner:” to pytest.
result = parse('1,3')
assert result == [1, 3]
The default test runner in PyCharm is the unittest library. Let’s configure PyCharm to run this
using pytest. Open ”Preferences” and search for ”Python Integrated Tools”. From that window, you
can change the ”Testing” -> ”Default test runner:” option to pytest.
With the default test runner set to pytest, you should see a green triangle appear in the gutter
next to test_basic. If you click on that, you can run the tests (or profile them, or collect coverage
information). Click on ”Run ’pytest for test_pars...’” (ctrl-shift-F10) and you will see that a ”Run”
tab appears below with an error.
The pytest library is not in the standard library. My project does not have pytest installed, so I
need to do that. You’ve got a couple options to install it. The ”Python Integrated Tools” window
has a warning at the bottom that says ”No pytest runner found in selected interpreter”. There is a
”Fix” button that you can click to install it. Alternatively, you can add the line:
import pytest
into test_parser.py and use the code intention to fix the import.
At this point, we will get an ImportError because we haven’t implemented parse. Let’s do
that.
136
13.3. Writing a Test
Figure 132: Figure illustrating triangle next to test function that appears when pytest is set as the default test
runner.
Figure 133: Figure illustrating TDD error. The code we are testing hasn’t been implemented yet.
137
13. Unit testing
13.4 Implementing Logic
Because we are using test-driven development (TDD), the functionality of the parse function
is being determined by our tests. We need to implement the ability to specify lists of integers
separated by commas. Here is one possible implementation:
def parse(txt):
result = []
for num in txt.split(','):
result.append(int(num))
return result
If you re-run the test you should see output like this:
===================== test session starts ============================
platform darwin -- Python 3.7.2, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: /Users/matt/PycharmProjects/TestExample, inifile:
collected 1 item
test_parser.py . [100%]
This output tells you what operating system you are on (darwin is for MacOS), and what version
of Python and pytest libraries you are using. (The py and pluggy libraries are dependencies of
pytest). The ”rootdir” is the directory that pytest uses to search for test files in. The ”inifile” is a
pytest.ini (or setup.cfg or tox.ini file) used to customize pytest behavior. In this case, there
was no inifile. The next line reports that pytest found 1 test. There was a test in test_parser.py
and it was 100% of the tests. If you look closer at that line, you will see a period. That indicates that
the test in test_parser.py passed. The pytest library has other statuses for tests, among them,
are s (skipped), F (fail), and E (exception).
test_parser.py F
test_parser.py:3 (test_basic)
[1, 3] != []
Expected :[]
Actual :[1, 3]
<Click to see difference>
138
13.6. Adding More Tests
def test_basic():
result = parse('1,3')
> assert result == []
E assert [1, 3] == []
E Left contains more items, first extra item: 1
E Use -v to get the full diff
test_parser.py:6: AssertionError
[100%]
def test_basic():
result = parse('1,3')
> assert result == []
E assert [1, 3] == []
E Left contains more items, first extra item: 1
E Use -v to get the full diff
test_parser.py:6: AssertionError
=================== 1 failed in 0.10 seconds =========================
Process finished with exit code 0
Rather than only notifying us that the assertion failed, pytest does some nifty tricks to show
you why the assertion failed. There is also integration in PyCharm to pull up the ”Comparison
Failure” window if you click on <Click to see the difference>.
Along the left side of the ”Run” tab at the bottom of PyCharm are buttons for ”Rerun pytest”
(ctrl-F5), ”Rerun Failed Tests”, and ”Toggle auto-test”. Rerunning failed tests is a great way to
quickly fix failing tests without the distraction of passing tests. Auto-test is a mode for running
the tests anytime the code changes. There is a slight delay after changing the code, then the tests
automatically run.
Note
There are many features that pytest has, that PyCharm doesn’t expose, but you can access them
from the ”Terminal” window. For example running:
pytest -x --lf
will run the last test that failed first. And it will stop after the first failure. This is a great
invocation to focus on fixing one failed test case at a time. When you move code to a different
platform or refactor code, this is really handy.
Once you have a pytest run configuration in PyCharm, you can open the “Edit configurations” in the
top right where you normally select which configuration will run and enter -x –lf in the “Additional
Arguments” to have PyCharm run with this option.
139
13. Unit testing
def test_dash():
result = parse('1-3')
assert result == [1, 2, 3]
Be careful, if you clicked the triangle in the gutter to run test_basic previously, clicking on the
green triangle on either the Run tab or the triangle on the top (the ”Run” command), PyCharm will
only run the test_basic test and not the new test. In the name of the run configuration you will
see ”pytest for test_parser.test_basic”, indicating that the run configuration is only for the single
test.
You can use the ”Edit Configurations...” command to change the ”Target:” from
test_parser.test_basic to test_parser and then the ”Run” (shift-F10) command will
run all the tests in the file.
Note
In real-world projects we could have multiple test files. If would be nice if PyCharm could run
all of the tests with a single click.
If you change the ”Target:” to a ”Script path” and set it to ”.” (a period without quotes),
PyCharm will run all of the test files found in the working directory.
The output from running all of the tests should look like this:
Testing started at 14:12 ...
~/.venvs/bin/python /Applications/PyCharm.app/_jb_pytest_runner.py
--path test_parser.py
Launching pytest with arguments test_parser.py in
/Users/matt/PycharmProjects/TestExample
test_parser.py .F
test_parser.py:7 (test_dash)
def test_dash( ):
> result = parse('1-3')
test_parser.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
txt = '1-3'
def parse(txt):
result = []
for num in txt.split(','):
> result.append(int(num))
E ValueError: invalid literal for int() with base 10: '1-3'
numparser.py:15: ValueError
[100%]
140
13.7. Testing Exceptions
def test_dash( ):
> result = parse('1-3')
test_parser.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
txt = '1-3'
def parse(txt):
result = []
for num in txt.split(','):
> result.append(int(num))
E ValueError: invalid literal for int() with base 10: '1-3'
numparser.py:15: ValueError
========== 1 failed, 1 passed in 0.15 seconds ======================
Process finished with exit code 0
which contains a period and an ”F”. The period is for the passing test and the ”F” is for the
failing test, which is raising a ValueError.
Let’s update the implementation in numparser.py to support dashes:
def parse(txt):
result = []
for num in txt.split(','):
if '-' in num:
start, end = num.split('-')
result.extend(range(int(start), int(end)+1))
else:
result.append(int(num))
return result
141
13. Unit testing
It looks like it will raise a ValueError if a string is passed in. Let’s write a test to handle that.
Until now, nowhere in our test_parser.py file was there a reference to pytest. When we
invoke the tests with pytest, pytest is able to determine what is a test and how to handle assert
statements. However, the assert statement can’t handle exceptions. For that, we need to use a
special context manager, raises, found in pytest. Update the test_parser.py file to:
from numparser import parse
import pytest
def test_basic():
result = parse('1,3')
assert result == [1, 3]
def test_dash():
result = parse('1-3')
assert result == [1, 2, 3]
def test_bad():
with pytest.raises(ValueError):
parse('bad')
We can use the with statement along with the pytest.raises context manager to test that an
exception occurred in the block of the context manager.
The pytest library has many other features that could fit in a book of their own. We encourage
you to explore the library further and take advantage of it for testing in Python. In addition to the
many features it ships with, it has a rich ecosystem of plugins to further enhance it.
Note
You will need to install a library for coverage. When you the ”Run ’pytest for test_parser’ with
Coverage” command, you will have the option to install the coverage.py library.
When PyCharm is properly configured for running coverage, a ”Coverage” tab will appear
after running the coverage command. This tab will show summary statistics for code coverage.
Typically, we are most concerned with the coverage numbers for non-test code. Another nice
integration with PyCharm is that the coverage results are shown in the gutter. There is a green
or red color in the gutter next to the line to indicate if there was code coverage.
142
13.8. Code Coverage
143
13. Unit testing
For our parse function, we have 100% coverage. A few words on coverage numbers. Higher
numbers are better than lower numbers. But, 100% coverage only means that the lines were
executed, it does not mean that the code is free from logic errors. Also, most code coverage tools
only deal with line coverage. As programs are executing, there are ”branches” and ”paths” through
the code that can change depending on the input to the code.
A more exhaustive type of testing and coverage is full path coverage, testing different possible
paths through the code. In practice, this type of coverage is difficult because most tools do not offer
support for it, but it also requires much dedication to understanding the code and the combinations
of execution paths. Most companies that have metrics around coverage pick a number they would
like to hit and strive not to have new commits to the code lower that number.
13.9 Summary
In this chapter, we used test driven development to implement a function to parse strings into lists
of numbers. We used to pytest library because it makes test creation very easy. We barely scratched
the surface of the functionality of this library. Finally, we used the integration in PyCharm to look
at code coverage statistics. Having access to these libraries in an integrated environment is a huge
boon to Python developers.
13.10 Commands
• ”Run ’pytest for test_pars...’” - (ctrl-shift-F10)
• ”Toggle auto-test”
13.11 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/10-testing to use pytest on an exist-
ing project.
144
Chapter 14
When you include an import to the numpy library, PyCharm will sense that and ask if you want
to turn on scientific mode. For the next example, we will pull fuel economy data and plot the
number of makes a car vendor had for each year. Given the right data, the pandas library can
make quick work of this. Create a new project with the following layout:
Data/
explore.py
#%%
auto = pd.read_csv(
'https://www.fueleconomy.gov/feg/epadata/vehicles.csv.zip')
#%%
# Just look at Ford, Lexus, & Toyota
(auto
.groupby(['year', 'make'])
145
14. Data science tools
Figure 141: Figure illustrating running code with a plot in scientific mode.
.size()
.unstack('make')
.loc[:,['Ford', 'Lexus', 'Toyota']]
.plot(kind='bar', figsize=(14,10))
)
plt.show()
Note
The parentheses around the pandas code look a little weird to most Python developers. This is
common in pandas because we tend to chain operations. With the parentheses, we don’t need
to have all of the code on a single line. We put each operation in the chain on its own line, and
it makes it easier to understand what is happening.
This code will group the data by year and make, then it will calculate the size of each group,
then it will pull the make column (really an index) into a row (giving us every make for each
year), then it pulls off only Ford, Lexus, and Toyota, and finally plots a bar plot.
If you were to type in this code, PyCharm would ask if you wanted to go into ”Scientific Mode”
when it sees the numpy line. My code imports matplotlib, but doesn’t call it. I did that so I could use
the code intention to easily install it. (Alternatively, you could open the terminal and pip install
it). You also need to install pandas.
If you run this code, it might think for a bit, but in the ”SciView”, there will be a ”Plots” tab
with the resultant plot.
146
14.3. Notebook Mode
You will also notice that in the ”Python Console” window, there is an ”explore” tab with an
interpreter. That interpreter has the namespace of explore.py. From there we can access the auto
dataframe, and interact with the data. If you have installed iPython (pip install ipython from
the ”Terminal”), you will get an iPython prompt instead of a normal Python prompt.
On the right side is a list of the variables in the namespace. In this case, only auto is there.
There is a clickable area titled ”View as DataFrame”. When you click it, the SciView tab for ”Data”
will be populated with a table of the data.
One more thing to note. Because our code contained comments starting with #%%, PyCharm
recognizes this a ”cell” of code. The cell consists of the code starting following that comment until
the next #%% comment. It puts a green execute triangle next to each cell and we can run, or re-run
those cells independently. PyCharm conveniently creates a cell for the initial code before the first
#%%.
Using Python with the interpreter and access to previous variables is great for interactive
exploration.
If you have created a new virtual environment for this project, you will need to install these
libraries. Click on the library name (with the redline under it) and you will get a code intention
for installing the libraries. If you click the green triangle, to run ”Execute Code Cell” (ctrl-enter),
PyCharm should start Jupyter and run the code.
After executing the cell. The notebook view will show a number next to a cell, and show any
output that was generated. Because this cell has no output, it will say ”No output”.
To create a new cell, add the comment above where you want the cell to start. Alternatively,
you can click on the plus in the gutter to create a code cell or a markdown cell.
Add the following code to the notebook:
#%%
auto = pd.read_csv(
'https://www.fueleconomy.gov/feg/epadata/vehicles.csv.zip')
#%%
147
14. Data science tools
148
14.3. Notebook Mode
Figure 143: Figure illustrating a new Jupyter notebook, and prompt to install the ”jupyter” package..
Figure 144: Figure illustrating running a cell when starting a new Jupyter notebook.
149
14. Data science tools
If you run these cells, you will see that PyCharm embeds the plot in the notebook area.
150
14.4. Summary
Note
If you were planning on also using this notebook with the Jupyter browser interface, you should
all the cell magic for displaying plots in the browser. Cell magics are directives to control how
Jupyter behaves. I would add the following line to cell containing the imports:
%matplotlib inline
Additionally, PyCharm provides a ”Jupyter” tab that displays the variables from the notebook.
You can click that tab to explore the variables. In this case it only shows the auto variable.
14.4 Summary
This chapter introduced Scientific Mode and support for Jupyter notebooks. When used for
analysis, it is common to use the REPL and interactive nature to try things out and quickly examine
the data. This style of programming is quite different from application development, where we
try to avoid using global variables and tend to write functions and classes. This isn’t to say that
normal Python developers don’t use the REPL (they should definitely take advantage of it), or
espouse bad programming practices like using global variables. When I’m doing some data science
consulting for clients, I use Jupyter to explore and create models. After I’m satisfied with the results,
I will refactor the code and apply engineering practices to introduce functions, classes, testing, and
packaging to the analysis. PyCharm has you covered here for the full range of development styles.
151
14. Data science tools
14.5 Commands
• import numpy - Include this is prompt for Scientific Mode
14.6 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/11-scientific-computing to create
a plot in scientific mode.
152
Chapter 15
Tool Windows
Note
This is not a substitute for using a proper bug tracker.
153
15. Tool Windows
This makes it easy to import source code found in your project and use the dependencies in the
virtual environment.
Although this looks similar to the Python REPL you see when you call python3 from the
command line, it has a few tricks up its sleeves. It comes with the code completion included in
the Python editor. Simply hit tab after starting to type a variable name or period. You can also pull
up ”Basic Code Completion” (ctrl-space).
You can navigate through the history of commands using the up and down arrow. If you had a
typo when typing out a function in the Python Console, you can hit the up arrow, and fix the typo
rather than typing out the whole function again.
The tab window also has a variable inspection area. Local variables are displayed there.
Imported modules can be found under the ”Special Variables” section. The variables can be
inspected there. Nested variables such as lists and dictionaries can be expanded to view parts
of the variable. In addition, you can run the ”Set Value...” (f2) command to change the value of a
variable or a nested value.
The Python Console also appears when you run a ”Run Configuration” (there is an option in
the Python configuration for ”Run with Python console”). By using a Run Configuration, you will
have access to all of the global variables in a file without having to import them.
If you want to run a specific portion of code, you can type it in directly in the Python Console.
You can also highlight code in the editor and run ”Execute Selection in Console...” (alt-shift-e). If you
execute the definition of a function by executing a selection, you won’t see the function name in
the variable inspection area unless you expand the ”Special Variables” hierarchy.
154
15.4. The Run Tool Window
A nice feature of the Python console is that it stays open after execution. This gives you the
ability to inspect variables and interact with the global namespace even when the code has finished
executing.
155
15. Tool Windows
Figure 153: Figure illustrating Python console with code completion and variable inspection.
on Windows or Unix.
If you prefer other shells, you can go to the ”Terminal” section of the Settings window. Under
the ”Application settings” area is a ”Shell path” entry. You can specify powershell on Windows,
or bin/zsh for Zsh.
If you want another Terminal, click on the ”New Session” (the plus button) command. This is
useful if you have a long-running process going in a terminal and want to perform another action
while it is running. A few other tricks include the ability to paste using the middle mouse button
(I wish this worked in editor windows), and cycling through previous commands with the up and
down arrows.
156
15.6. The Favorites Tool
Figure 155: Figure illustrating Terminal running a command in the virtual environment.
The Terminal is tightly integrated for running various command line tools. It works very
well for package management and running shell tools (such as Django’s manage.py script) on all
platforms. Minimizing task switching by limiting changing applications is helpful for maintaining
focus.
157
15. Tool Windows
In web applications, you might have to edit model and view code in Python, as well as
JavaScript and CSS when adding a feature or fixing a bug. You can create a new favorite list and
add all of the files to it.
To add a file to favorites, use the ”Add to Favorites” command (alt-shift-f, File -> ”Add To
Favorites”, right-click on a file in the Project view, or right-click on the tab in the editor). If you
want to add all of the open files to a favorite, you can right-click on one of the tabs in the file editor
and click ”Add All To Favorites”.
A bookmark is like a favorite, but more fine-grained. Rather than referring to a file, a bookmark
refers to a line in a file. You can ”Toggle Bookmark” (f11 or Navigate -> ”Bookmarks” -> ”Toggle
Bookmark”) when on a line of code.
In addition, you can create a ”mnemonic” bookmark. With the ”Toggle Bookmark with Mnemonic”
(command-f11 or ctrl-f11), PyCharm will bring up a dialog to select a cell. The cells are single
character alphanumerics. If you select ”1” as the cell, there will be a new keyboard ”Go to Bookmark
<1>” shortcut (ctrl-1) to navigate to the mnemonic bookmark. You can also use the ”Favorites”
window to navigate to bookmarks.
Bookmarks are very useful for tracking particular lines in files. Take advantage of mnemonic
bookmarks for quick navigation to commonly used lines of code.
Finally, the Favorites window allows easy viewing and navigation to breakpoints. When you
run the ”Toggle Breakpoint” (command-f8 or ctrl-f8) or click in the gutter next to the code, the
158
15.6. The Favorites Tool
Figure 157: Figure illustrating right-clicking to add a file to the Favorites Window.
159
15. Tool Windows
breakpoint will appear in the favorite view. Again, by clicking in the favorites window, you can
navigate to a breakpoint.
160
15.8. Summary
15.8 Summary
There are a bunch of tools that while not strictly necessary, can greatly improve your coding
experience. The Todo window lets you track areas where you need to update or change the code.
The console window has an integrated Python REPL for exploring and experimenting with your
project. The Run window appears when you run code and shows you the output of your execution.
The terminal window provides quick access to your virtual environment and command line scripts.
The favorites window lets you navigate and remember files and code that you commonly use.
Finally, the structure window summarizes the code in a file. Take advantage of these windows
when working with your project.
15.9 Commands
• ”TODO” - (command-6 or alt-6)
• ”Autoscroll to Source”
• ”View Options”
• ”Preview Source”
• ”Python Console” - (Tools -> ”Python Console...” or click on ”Python Console” tab)
• ”Rerun” - (ctrl-f5)
• ”Pause Output”
• ”Terminal” - (alt-f12)
• ”New Session”
• ”Add to Favorites” - (alt-shift-f, File -> ”Add To Favorites”, right-click on a file in the Project
view, or right-click on the tab in the editor)
161
15. Tool Windows
• ”Toggle Bookmark” - (f11 or Navigate -> ”Bookmarks” -> ”Toggle Bookmark”)
15.10 Exercises
1. Using your favorite project try using the Todo window.
2. Using your favorite project try to run the code with the Console window.
3. Using your favorite project, open the terminal window and run some commands. Try to
invoke Python. List the packages that pip has installed.
4. Using your favorite project try using the Favorites window to navigate between functions
and files.
5. Using your favorite project try using the Structure window to explore the code in your project.
162
Chapter 16
Note
Many of these plugins are open source, while some are proprietary. As with many things on
the Internet, there can be nefarious code. Buyer beware.
The plugin page in PyCharm will show a ”Restart IDE” button. Click that to use the new plugin.
Now when you perform a command using the mouse, this plugin will indicate the keyboard
shortcut.
24
http://www.jetbrains.org/intellij/sdk/docs/welcome.html
163
16. Extending PyCharm with Plugins
164
16.3. Installed Plugins
Figure 163: Figure illustrating the Key Promotor X showing the shortcut for the breakpoint command.
16.4 Summary
PyCharm works by using plugins. The built-in plugins define the behavior for PyCharm. In
addition, there are over a thousand plugins that you can install as well. If you need specific
behavior for PyCharm, check to see if there is a plugin that supports that behavior.
16.5 Commands
• ”Preferences...” window - (command-, or ctrl-alt-S)
16.6 Exercises
1. Check out https://github.com/talkpython/mastering-pycharm-course Follow the instruc-
tions for the new project in tree/master/your-turn/13-plugins to explore existing plug-
ins.
165
16. Extending PyCharm with Plugins
166
Chapter 17
Conclusion
167
17. Conclusion
PyCharm professional also ships with robust JavaScript tooling. You can refactor JavaScript
in PyCharm. You can also create TypeScript from PyCharm. PyCharm has plugins that support
Angular, Vue, React, LESS, and more.
Developers spend a large amount of time reading and debugging code. PyCharm has a
graphical debugger that enables you to set breakpoints, walk through code, and inspect values.
PyCharm also has ”inline debugging” and will show you the values of the variables next to the
code itself. Using the debugging functionality should allow you to understand code and fix bugs
with minimal effort.
PyCharm has support for Python packaging. You can run tasks on existing setup.py files. You
use the ”Create setup.py” command to walk you through creating a new package with minimal
pain. In addition to making it easy to create Python code, you can also create packages and share
that code with others. PyCharm has you supported through the whole process.
In addition to debugging, PyCharm has profiling capabilities. There is no additional
configuration required. If you can run your program, you can profile it. The profile report will
show you a table of call count and time spent. You can also view a call graph to determine what
code is calling slow code.
Because Python is not a compiled language, testing is very important to ensure that code runs
and works correctly. (Not that compiling guarantees that code runs correctly). Python supports
the built-in unittest library and also works with the pytest library. Investing some time learning
the pytest library will pay dividends in writing better Python code. PyCharm also ships with code
coverage support. You can quickly look at the gutter and determine if you have a test that covers
a line of code. Again, you get this functionality by clicking on a button. Once you have a run
configuration, you get profiling and code coverage for free.
Python is one of the top tools of data scientists. PyCharm has support for workflows that this
type of work requires. The scientific mode lets PyCharm get you quick feedback on data analysis
and results of models that you run. There is also support for Jupyter notebooks from PyCharm.
There are a bunch of tool windows in PyCharm that will make your life easier. The Todo
window tracks items you would like to change in the future. The run tool and Python console
let you run code and inspect live variables. The terminal lets you interact with your virtual
environment. You can track files and lines in files with the favorites window. Finally, the structure
window gives you a high-level view of your classes, functions, and variables.
PyCharm has many plugins that you can take advantage of. If you need extra functionality,
make sure that you check for a plugin. We showed how to use the Key Promoter X plugin to aid
in remembering keyboard commands.
168
17.3. Thanks and Goodbye
17.3 Thanks and Goodbye
Thanks for reading this book. We enjoyed writing it and hope that you have learned a lot
while reading it and doing the exercises. Feel free to follow us on twitter, our handles are
@__mharrison__ and @mkennedy. If you enjoyed this book, please consider leaving a review on
Amazon. That is the best way for other people to find out about it. Please feel free to link to if from
social media.
169
About the Authors
Matt Harrison runs MetaSnake, a Python and Data Science consultancy and corporate training
shop. In the past, he has worked across the domains of search, build management and testing,
business intelligence, and storage.
He has presented and taught tutorials at conferences such as Strata, SciPy, SCALE, PyCON,
and OSCON as well as local user conferences. The structure and content of this book is based on
first-hand experience teaching Python to many individuals.
He blogs at hairysun.com and occasionally tweets useful Python related information at
@__mharrison__.
171
About the Authors
Michael Kennedy is the host of Python Bytes and Talk Python to Me. He is also the founder of
Talk Python training and a Python Software Foundation fellow. Michael has been working in the
developer field for more than 20 years and has spoken at numerous conferences.
Follow Michael on twitter where he is @mkennedy.
172
Index
Index
173
Index
language injection, 86 Reformat Code, 35
Lens mode, 49 register, 124
less, 105 Rename, 47, 75
Live template, 53 REPL, 154
Live templates, 38 requirements.txt, 26
Local History, 62 Rerun, 113
Locate Duplicates, 72 Resource Root, 96
Resources Root, 22
magic numbers, 77 Resume, 113
main, 38 Revert, 57
mark directory, 96 Run configuration, 19
Mark directory as, 22 Run Cursor To, 114
Mnemonic Bookmark, 158 Run files, 19
Modify Column, 85 Run setup.py Task..., 122
Modify Table, 85
module, 79, 122 Scientific mode, 145
Move, 78 sdist, 124
Mute Breakpoints, 113 Search Everywhere, 28
Set value, 154
Navigate to declaration, 29 Set Value..., 115
New Project..., 89 Settings, 24
New Session, 156 setup.py, 119, 123
New Watch, 115 Show Execution Point, 114
New..., 123 Show History, 57
Notebook mode, 147 Show intention, 43
NPM, 103 Show intention actions, 33
Open Console, 84 Show on call graph, 131
Open Task, 63 Show Visualization, 83
Single instance only, 92
package, 79, 122 Smart Step into, 114
package.json, 103 Source Control, 57
Parameter info, 38, 51 Sources Root, 21, 22
Pause, 113 Step In, 114
Plugins, 163 Step In (My Code), 114
Powershell, 155 Step Over, 114
Preferences, 24 Stop, 113
Profile, 130 Structure Window, 160
Pull Members Up, 73 Synchronize, 85
Push, 58 syntax highlighting, 40
PyPI, 124 sys.path, 154
pytest, 135
Python console, 154 Terminal, 24, 155
testing, 135
Quick Documentation, 51 theme, 40
Todo, 153
raises, 142
Toggle Bookmark, 158
Recent Files, 28 Toggle Breakpoint, 158
Refactor Method, 44 TypeScript, 102
Refactor This, 73
174
Index
Update Project, 57
upload, 124
Version Control, 57
View Breakpoints, 113
View Pull Request, 67
Virtual Environment, 155
Virtual environment, 19, 22, 23
Watches, 115
Zen Coding, 95
175
Also Available
Illustrated Guide to Python 3 by Matt Harrison is the book to teach you Python fast. Based on
years of experience teaching Python at small and large companies. Designed to up your Python
game by covering the fundamentals:
• Interpreter Usage
• Types
177
Also Available
• Sequences
• Dictionaries
• Functions
• Classes
• Exceptions
• Importing
• Libraries
• Testing
• And more …
Reviews
If you want to go from being able to write runnable Python scripts to the beginning
levels of being able to follow pycon tutorials, this is the book for you.
Ben Jones
I like this book for people learning Python. I teach Python Programming Fundamentals
and this is one of the textbooks I recommend to my students. Very good explanations.
PurpleDiane
178
Learning the Pandas Library
Learning the Pandas Library
Learning the Pandas Library: Python Tools for Data Munging, Analysis, and Visualization by Matt
Harrison is the book to teach you the ins and outs of Pandas. It includes many examples, graphics,
code samples, and plots from real world examples.
• Data Structures
• Series CRUD
• Series Indexing
• Series Methods
• Series Plotting
• DataFrame Methods
• DataFrame Statistics
179
Also Available
• Joining DataFrames
• And more …
Reviews
If you already have some background in python but are not a total expert in pandas, I
strongly recommend this book. I walks you and motivates through the data structures
that are used in pandas en explains their raison d’être. The style is easy read.
Luis-Durham
This book provides tons of practical solutions that I’ve been able to implement at work
immediately after reading. Definitely a nice guide to have handy.
Darian P
180
One more thing
181