Python Good Practices
Virtual Environments
A virtual environment is a private copy of the Python interpreter, onto which you can install packages privately, without affecting the global Python interpreter installed in your system.
The more projects you have, the more likely it is that you will be working with different versions of Python itself, or at least different versions of Python libraries. For this reason, we use virtual environments.
For instance, you can always check your environment configuration with:
$ pip freeze
Virtualenv
Install virtualev:
sudo pip install virtualenv
Create a virtual environment:
$ virtualenv venv
To begin using the virtual environment, it needs to be activated:
$ source venv/bin/activate
If you are done working in the virtual environment for the moment, you can deactivate it:
$ deactivate
To delete a virtual environment, just delete its folder.
Virtualenvwrapper
Virtualenvwrapper provides a set of commands and also places all your virtual environments in one place.
To install it, make sure virtualenv is already installed, then:
$ pip install virtualenvwrapper
Add this to your .bashrc file:
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/Devel
source /usr/local/bin/virtualenvwrapper.sh
To create a virtual environment:
$ mkvirtualenv test
To check if it is working:
$ which python
$ pip freeze
To work on a virtual environment:
$ workon test
To deactivate the environment:
$ deactivate
To delete it:
$ rmvirtualenv test
Why?
Because now we can have a file with all the requirements of your project, and install it anywhere you setup your work environment with:
pip install -r requirements.txt
Debugging
pdb, the Python debugger:
An introduction to pdb can be found here.
For example, you can use the option -i to run a script, and then it goes to an interactive session with the Python interpreter:
$ python -i
Another way of debugging is by setting traces inside your code. For instance, you can write the following snippet inside the function that you want to inspect:
import pdb
pdb.set_trace() # where you want to start to debug
When running from the console, some useful commands are:
(Pdb) list <- show next 10 lines
(Pdb) p self <- point
(Pdb) n <- next line
(Pdb) help
(Pdb) exit
Unit Tests
Unittest
- Standard testing package in Python standard library.
- The files must start with test_.
- Test isolation: Every test gets a new test object, failure does not stop tests, and test do not affect each other.
- use
self.assert...
instead of Python'sassert
to show not only the failed value but also the actual value.
import unittest
class BasicsTestCase(unittest.TestCase):
def test_find_name(self):
self.assertTrue(1 == 1)
self.assertFalse(1 == 2)
if __name__ == '__main__':
unittest.main()
Run with:
$ python -m unittest <filename>
- Good practices: use a main test case class, use setup and teardown methods.
Scripting
You can add a custom command to a script in your app, such as manage.py:
@manager.command
def test():
"""Run the unit tests."""
import unittest
tests = unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests)
To run:
$ python manage.py test
pytest
To use pytest, you just need to include a function that starts with test_ in a file that starts with test_. More information here.
You install with:
$ pip install pytest
For example, create a file with:
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
And run with:
$ py.test
You can also drop this to pdb:
$ py.test --pdb
Doctest
The test is run on everything in docstrings:
'''
>>> 1 == 1
False
'''
if __name__ == '__main__':
import doctest
doctest.testmod()
nosetest
Nose finds all the files that start with test and run for you. More information here.
# run tests over the directory
$ nosetest
Coverage
Code coverage tools measure how much of the application is exercised by unit tests
and can provide a detailed report that indicates which parts of the application code are
not being tested. To install coverage in Python:
$ pip install coverage
To run from the command line:
$ coverage run file.py
$ coverage report -m
Finally, you can create a HTML coverage version:
$ coverage html
Scripting
We can integrate the coverage metrics to a manage.py file in our application. For example:
#!/usr/bin/env python
import os
COV = None
if os.environ.get('FLASK_COVERAGE'):
import coverage
COV = coverage.coverage(branch=True, include='app/*')
COV.start()
@manager.command
def test(coverage=False):
"""Run the unit tests."""
if coverage and not os.environ.get('FLASK_COVERAGE'):
import sys
os.environ['FLASK_COVERAGE'] = '1'
os.execvp(sys.executable, [sys.executable] + sys.argv)
if COV:
COV.stop()
COV.save()
print('Coverage Summary:')
COV.report()
basedir = os.path.abspath(os.path.dirname(__file__))
covdir = os.path.join(basedir, 'tmp/coverage')
COV.html_report(directory=covdir)
print('HTML version: file://%s/index.html' % covdir)
COV.erase()
To run:
$ python manage.py test --coverage
Unicode and Style
All strings are Unicode in Python 3. However, in Python 2, there are lots of problems with UTF-8 and ASCII conversion. You can use codecs module:
import codecs
An example of code before:
with open("doc.txt", "r") as f:
lines = [line.strip('\n') for line in f]
print lines
Now, using codecs:
with codecs.open("doc.txt", encoding='utf-8') as f:
lines = [line.strip('\n') for line in f]
print lines
Finally, you should know that the convection used when you write a code in Python are deffined by PEP 8 (Python Enhancement Proposal 8).
To fix style issues, you can use pep8ify.
--
Interpreters
Now, let us talk about the interpreter: the command line environment to directly run code. The first one is the REPL (Read-Evaluate-Print Loop), which comes with the Python installation. You use it simply typing:
$ python
A second option is IPython, which allows you to make notebooks suitable for the web.
Finally, you can use bpython, which has a great GUI integrated with Python's documentation.
Further References
Written by bt3gl
Related protips
1 Response
you should know that the convection used when you write a code
Typo.