Compiled from the “Development Tips” series, collecting common problems and solutions in Python and Django development.
1. Sorting Python Iterables
Iterable objects fall into 3 main categories:
- All sequence types, such as list, str, and tuple
- Some non-sequence types, such as dict and file
- Objects that contain an
__iter__()or__getitem__()method
sort is a method of the list object, while sorted can sort any iterable object. The difference is that sort rearranges the list in place, whereas sorted() produces a new list. Basic concepts related to sorting:
- iterable
The iterable object - cmp
Comparison function, requires two arguments - key
The element used for comparison, takes only one argument - reverse
Sort rule: reverse = True for descending, reverse = False for ascending
1.1 The sort Function
Prototype:
| |
Usage example:
| |
| |
1.2 The sorted Function
Prototype:
| |
Usage example:
| |
| |
You can specify multiple sort keys: first by x[1], then by x[0].
| |
2. Serialization and Deserialization in Python
Serialization is the process of converting an in-memory object into a storable or transmittable sequence. Deserialization is the process of converting that serialized sequence back into an in-memory object. Json and Pickle are the two serialization modules commonly used in Python.
Json VS Pickle:
- Json converts between in-memory objects and Json strings; Pickle converts between in-memory objects and byte objects
- The Json format is widely used outside Python as well; Pickle is unique to Python
- Json can only serialize Python’s built-in basic data-type objects, while Pickle can serialize any object, including functions
- cPickle is the C-language implementation of Pickle, commonly used to replace Pickle for better performance
Usage example:
| |
In addition, strings can be compressed to save storage:
| |
3. Python’s Logging Module
Python’s logging module consists mainly of four parts:
- Loggers: the interface programs can call directly
- Handlers: output log records to the appropriate destination
- Filters: provide finer-grained decisions on whether a log is emitted
- Formatters: customize the layout of the final printed record
Look at the following example, the file log1.py
| |
Running it directly outputs:
| |
The file log2
| |
Running it directly outputs:
| |
Some format parameters:
- %(levelno)s: prints the numeric log level
- %(levelname)s: prints the log level name
- %(pathname)s: prints the path of the currently executing program, which is actually sys.argv[0]
- %(filename)s: prints the name of the currently executing program
- %(funcName)s: prints the current function of the log
- %(lineno)d: prints the current line number of the log
- %(asctime)s: prints the time of the log
- %(thread)d: prints the thread ID
- %(threadName)s: prints the thread name
- %(process)d: prints the process ID
- %(processName)s: prints the thread name
- %(module)s: prints the module name
- %(message)s: prints the log message
4. Python Debugging Tools
- pdb
The Python Debugger is the official debugger, built into the Python standard modules.
Usage: $python -m pdb scriptfile or pdb.set_trace() in the code
- ipdb
An ipython-based pdb, an enhanced version of pdb.
Usage: $ipdb scriptfile or $python –pdb scriptfile
- PuDB
A full-screen, console-based visual debugger.
Usage: $python -m pudb.run scriptfile or $pudb scriptfile
5. Django CSRF
django.middleware.csrf.CsrfViewMiddleware processing logic:
Before entering the views function for processing, if there is a csrf token in the cookies, it is set in request.Meta; otherwise a token is generated. If the method is not GET, HEAD, etc., CSRF is validated.
Validation rule: the csrf token taken from the Cookie is compared with the csrfmiddlewaretoken or HTTP_X_CSRFTOKEN in the POST request. If the two are equal, validation passes; otherwise a 403 is returned.
Before returning the response, if CSRF_COOKIE_USED has been set, the csrf token is set into the Cookie. There are usually two ways to set CSRF_COOKIE_USED:
- Directly use the
django.middleware.csrf.get_tokenfunction to obtain the csrf token - Configure the
django.template.context_processors.csrfcontext processor to render the csrf token in the template, which in fact still calls the get_token function
Below is an excerpt from part of the Django source:
| |
Parameter explanations:
- max_age: the lifetime of the cookie, defaults to None; the cookie expires immediately when the browser closes
- expires: the point in time when the cookie expires, defaults to None; the cookie expires immediately when the browser closes
- path: the path where the Cookie takes effect; / means the root path, and a cookie on the root path can be accessed by pages at any url
- domain: defaults to None, the domain of the page that sets the Cookie is None
- secure: used to make the Cookie sent only over requests guaranteed to be secure. When the request is HTTPS or another secure protocol, a Cookie with the secure option can be saved to the browser or sent to the server.
- httponly: can only be transmitted over the http protocol and cannot be read by JavaScript (not absolute; it can be captured at a lower level by packet sniffing and can also be overridden). Defaults to False.
Django’s default configuration for CSRF:
| |
6. The djcelery_crontabschedule already exists Error
Versions used:
- Django==1.8.3
- celery==3.1.18
- django-celery==3.1.16
When upgrading to django-celery==3.2.2, running python manage.py migrate reports an error:
| |
The django-celery GitHub changelog mentions:
Starting with the 3.1.17 release, Django migrations were added.
If tables such as djcelery_* already exist, running $python manage.py migrate will then report an error. When upgrading dependency library versions, keep version compatibility in mind.
7. Handling Update Signals for Django Models
The created field lets you distinguish between create and update operations on a Django Model.
| |
8. Serving Static Files with WhiteNoise
Django’s built-in static file server is very inefficient, and WhiteNoise is a good replacement. It has the following characteristics:
- Usually used for PaaS services
- Supports wsgi applications, with special adaptation for Django
- Works better together with a CDN
- Combined with Gunicorn, it uses the sendfile system call, giving very high processing efficiency
- Compared with Nginx, WhiteNoise serves static files in a simpler way, but its efficiency is only 15% of Nginx’s
9. Recording Django Model Modification History
django-simple-history
How it works: each model that needs tracking requires its own separate table, and when an instance is modified a new record is created directly in that table.
django-reversion
How it works: when model data is modified, the modification is serialized into a Version table. Only one table is needed to record all modification history.
10. Python Memory Analysis Methods
Mainly involves four tools:
- memory_profile: analyzes the memory usage of each line of code
- objgraph: traces the relationships between objects in memory
- guppy: tracks heap usage at runtime
- pyrasite: injects code into a process
It is done in two steps:
- Simulate the production environment, using pyrasite and guppy to obtain heap information
- Based on the information from the previous step, locate a specific block in the code, then use memory_profile or objgraph to do further analysis
11. Python Multiple Inheritance
When calling methods in Python multiple inheritance, a depth-first search algorithm is used. In order, it searches one parent class deeply all the way down, then searches the second parent class, until the method is found.
- Old-style classes
Old-style class lookup order: C(A, B) => C -> A -> B
- New-style classes
One problem with new-style classes is that any subclass of multiple inheritance has a common ancestor class, Object, so it is always diamond inheritance. New-style classes look up methods in the order of the classes stored in Class.**mro**.
New-style class lookup order: C(A, B) => C -> A -> B -> Object
12. Replacing MySQL-python with pymysql
MySQL-python has stopped being updated, only supports Python2 and not Python3, and has complex dependencies that make it troublesome to install.
pymysql was created to replace MySQL-python. It is written purely in Python, its interface is compatible with MySQL-python, it is easy to install, and it supports Python3.
The replacement method is as follows:
| |
13. Connecting to Databases from Python3
Python3 mainly has two database connection clients: mysqlclient and PyMySQL.
- mysqlclient is implemented in C
- PyMySQL is implemented in Python
In terms of performance, mysqlclient is an order of magnitude faster than PyMySQL. However, under PyPy, PyMySQL and mysqlclient perform about the same.
If you need to use gevent or eventlet monkeypatched sockets, then choose PyMySQL.
14. MySQL Error Table ‘performance_schema.session_variables’ doesn’t exist
Running the following commands resolves it:
| |
Reference: Documented SHOW command behavior for show_compatibilty OFF and PFS builds
15. Exception Handling in Python2 and Python3
Two forms supported by both Python2 and Python3:
- With an argument
| |
- Without an argument
| |
A form only supported by Python2:
| |
16. get_object_or_404 and get_queryset in Django
get_object_or_404 retrieves an object using get, otherwise returns a 404
| |
Using get_queryset lets you customize query behavior globally, including in admin
| |
17. Tree Structure Storage
- Materialized path
Each node stores the encoding of its complete path.
| |
The advantage is that both reads and writes are very fast.
- Adjacency list model
The adjacency list representation stores the tree by keeping links to some adjacent nodes.
| |
The advantage is that the structure is simple and easy to understand, but when the data volume is large, recursion-based queries are very inefficient.
- Nested set
Each node stores some indices (usually left and right values).
| |
The advantage is that querying data is very fast, but on update a large number of nodes need to be modified.
- Interval nested set
The intervals are mapped into two-dimensional space, and each node corresponds to a score according to a rule. Hierarchical queries involving node positions do not need to access the database. The advantage is that performance is very good, but there is a bit of a barrier to implementing and understanding it.
django-treebeard implements materialized paths, nested sets, and adjacency lists. django-mptt mixes nested sets and adjacency lists, can efficiently query child nodes, and can rebuild the tree when it is corrupted.
18. Pytest Cannot Find Module Error
Error message:
| |
Cause:
Under the test directory, an __init__.py file exists, which causes Pytest to treat the whole test as a single module. What we actually need is for Pytest to enter the directory, find files starting with test_, and run the tests. Simply deleting the __init__.py file is enough.
19. Several Ways to Continue Lines in Python
1, Using a backslash
| |
2, Using parentheses
| |
20. Python Lists and Tuples Iterate at About the Same Speed
Run the following test code in IPython:
| |
| |
From the test results, list and tuple iterate at about the same speed. But you often hear the claim that tuple is faster than list, which actually refers to creation speed. In addition, their lookup speeds are about the same too.
In CPython, creating a tuple allocates a fixed, contiguous block of memory all at once; creating a list allocates two blocks of memory, one recording Python Object information and one used to store data.
21. Python’s Class Constructor type()
| |
Parameter descriptions:
- name, a string, specifies the name of the new class, assigned to the new class’s
__name__ - bases, a tuple, specifies the base classes of the new class, assigned to the new class’s
__bases__ - dict, a dictionary type, specifies the attributes of the new class, assigned to the new class’s
__dict__
As a dynamic language, Python can build classes dynamically to achieve many wonderful features and save a great deal of code.
22. The EAFP Principle in Python
Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the 07001 common to many other languages such as C.
For example:
EAFP style
| |
LBYL style
| |
LBYL requires searching the dictionary twice, and its readability is also worse than EAFP.
