Skip to content

Commit 4567a95

Browse files
authored
Merge branch 'master' into python-list
2 parents 75bf26c + e4c172c commit 4567a95

16 files changed

Lines changed: 318 additions & 2 deletions

ipython-console/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Code Snippets and IPython Cheat Sheet
2+
3+
This folder contains code resources and an IPython magic command cheat sheet based on the content of the Real Python tutorial [Unlock IPython's Magical Toolbox for Your Coding Journey](https://realpython.com/ipython-interactive-python-shell/).

ipython-console/employee.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
first_name = "Han"
2+
last_name = "Solo"
3+
department = "Accounts"
4+
salary = 1000
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import IPython
2+
3+
first_name = "Han"
4+
last_name = "Solo"
5+
department = "Accounts"
6+
print(f"{first_name} {last_name}")
7+
8+
IPython.embed()
9+
10+
salary = 1000

ipython-console/increment.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def salary_increment(salary):
2+
"""Calculate the new salary after applying an increment.
3+
4+
Args:
5+
salary (int): The current salary.
6+
7+
Returns:
8+
str: A string indicating the new salary after increment.
9+
"""
10+
increment = salary / 10
11+
new_salary = increment + salary
12+
return f"Your New Salary is: {new_salary}"
136 KB
Binary file not shown.

python-312/perf-profiler/benchmark_optimized.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def get_average_luminance(pixels):
3131
return exp(mean([log(luminance(pixel) + 1e-9) for pixel in pixels]))
3232

3333

34-
def mean(n):
35-
return sum(n) / len(n)
34+
def mean(numbers):
35+
return sum(numbers) / len(numbers)
3636

3737

3838
def luminance(pixel):

python-profiling/README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Profiling in Python: How to Find Performance Bottlenecks
2+
3+
This folder holds sample code that supplements the Real Python tutorial [Profiling in Python: How to Find Performance Bottlenecks](https://realpython.com/python-profiling/).
4+
5+
## Profiler 1: `time`
6+
7+
```shell
8+
$ python profile_time.py
9+
sleeper()
10+
Real time: 1.75 seconds
11+
CPU time: 0.00 seconds
12+
13+
spinlock()
14+
Real time: 1.80 seconds
15+
CPU time: 1.80 seconds
16+
```
17+
18+
## Profiler 2: `timeit`
19+
20+
```shell
21+
$ python profile_timeit.py
22+
Average time is 0.15 seconds
23+
```
24+
25+
## Profiler 3: `cProfile`
26+
27+
```shell
28+
$ python profile_cprofile.py
29+
fib(35) = 9227465
30+
29860712 function calls (10 primitive calls) in 9.487 seconds
31+
32+
Ordered by: call count
33+
34+
ncalls tottime percall cumtime percall filename:lineno(function)
35+
29860703/1 9.487 0.000 9.487 9.487 profile_cprofile.py:5(fib)
36+
1 0.000 0.000 0.000 0.000 pstats.py:118(init)
37+
1 0.000 0.000 0.000 0.000 pstats.py:137(load_stats)
38+
1 0.000 0.000 0.000 0.000 pstats.py:108(__init__)
39+
1 0.000 0.000 0.000 0.000 cProfile.py:51(create_stats)
40+
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
41+
1 0.000 0.000 0.000 0.000 {built-in method builtins.hasattr}
42+
1 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}
43+
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
44+
1 0.000 0.000 0.000 0.000 {built-in method builtins.print}
45+
```
46+
47+
## Profiler 4: `pyinstrument`
48+
49+
Make sure to install the third-party library [`pyinstrument`](https://pypi.org/project/pyinstrument/) from the supplied `requirements.txt` file into a virtual environment first:
50+
51+
```shell
52+
$ python3 -m venv venv/
53+
$ source venv/bin/activate
54+
(venv) $ python -m pip install -r requirements.txt
55+
```
56+
57+
Then, you can run the sample script while you're still in the same virtual environment:
58+
59+
```shell
60+
(venv) $ python profile_pyinstrument.py
61+
n = 10 [2.8, 2.8, 2.8, 3.2, 2.4]
62+
n = 100 [3.04, 3.28, 3.24, 2.92, 3.24]
63+
n = 1,000 [3.176, 3.192, 3.188, 3.076, 3.132]
64+
n = 10,000 [3.1376, 3.1328, 3.172, 3.1292, 3.1376]
65+
n = 100,000 [3.14636, 3.13424, 3.15104, 3.14212, 3.14612]
66+
n = 1,000,000 [3.141736, 3.141708, 3.14168, 3.141828, 3.140708]
67+
n = 10,000,000 [3.14143, 3.1403824, 3.1411704, 3.1408808, 3.1420068]
68+
69+
_ ._ __/__ _ _ _ _ _/_ Recorded: 11:49:03 Samples: 243
70+
/_//_/// /_\ / //_// / //_'/ // Duration: 24.334 CPU time: 24.298
71+
/ _/ v4.5.0
72+
73+
Program: profile_pyinstrument.py
74+
75+
24.300 <module> profile_pyinstrument.py:1
76+
└─ 24.300 estimate_pi profile_pyinstrument.py:6
77+
├─ 23.200 <genexpr> profile_pyinstrument.py:7
78+
│ ├─ 15.200 point profile_pyinstrument.py:14
79+
│ │ ├─ 7.700 Random.uniform random.py:520
80+
│ │ │ [4 frames hidden] random, <built-in>
81+
│ │ │ 6.200 [self] None
82+
│ │ └─ 7.500 [self] None
83+
│ ├─ 4.600 [self] None
84+
│ └─ 3.400 hits profile_pyinstrument.py:10
85+
│ ├─ 2.400 [self] None
86+
│ └─ 1.000 abs None
87+
│ [2 frames hidden] <built-in>
88+
└─ 1.100 [self] None
89+
```
90+
91+
## Profiler 5: `perf`
92+
93+
Make sure to follow the setup instructions in the [Python 3.12 Preview: Support For the Linux perf Profiler](https://realpython.com/python312-perf-profiler/) tutorial.
94+
95+
Next, record samples into a local binary file named `perf.data`:
96+
97+
```shell
98+
$ sudo perf record -g -F 999 $HOME/python-custom-build/bin/python3 -X perf profile_perf.py
99+
```
100+
101+
Finally, display a report by issuing the following command while you're in the same folder:
102+
103+
```shell
104+
$ sudo perf report
105+
```
106+
107+
For an alternative view, try this instead:
108+
109+
```shell
110+
$ sudo perf report --hierarchy --sort comm,dso,sample
111+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from cProfile import Profile
2+
from pstats import SortKey, Stats
3+
4+
5+
def fib(n):
6+
return n if n < 2 else fib(n - 2) + fib(n - 1)
7+
8+
9+
with Profile() as profile:
10+
print(f"{fib(35) = }")
11+
Stats(profile).strip_dirs().sort_stats(SortKey.CALLS).print_stats()

python-profiling/profile_perf.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from concurrent.futures import ThreadPoolExecutor
2+
3+
4+
def find_divisors(n):
5+
return [i for i in range(1, n + 1) if n % i == 0]
6+
7+
8+
def slow_function():
9+
print("Slow thread started")
10+
try:
11+
return find_divisors(100_000_000)
12+
finally:
13+
print("Slow thread ended")
14+
15+
16+
def fast_function():
17+
print("Fast thread started")
18+
try:
19+
return find_divisors(50_000_000)
20+
finally:
21+
print("Fast thread ended")
22+
23+
24+
def main():
25+
with ThreadPoolExecutor(max_workers=2) as pool:
26+
pool.submit(slow_function)
27+
pool.submit(fast_function)
28+
29+
print("Main thread ended")
30+
31+
32+
if __name__ == "__main__":
33+
main()
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from random import uniform
2+
3+
from pyinstrument import Profiler
4+
5+
6+
def estimate_pi(n):
7+
return 4 * sum(hits(point()) for _ in range(n)) / n
8+
9+
10+
def hits(point):
11+
return abs(point) <= 1
12+
13+
14+
def point():
15+
return complex(uniform(0, 1), uniform(0, 1))
16+
17+
18+
for exponent in range(1, 8):
19+
n = 10**exponent
20+
estimates = [estimate_pi(n) for _ in range(5)]
21+
print(f"{n = :<10,} {estimates}")
22+
23+
24+
with Profiler(interval=0.1) as profiler:
25+
estimate_pi(n=10_000_000)
26+
27+
profiler.print()

0 commit comments

Comments
 (0)