from IPython.core.display import HTML
HTML(open("custom.html", "r").read())
A standard Python installation not only provides the Python interpreter, but also a huge collection of modules.
The reference documentation can be found at https://docs.python.org/3/library/index.html.
The website "python module of the weeks" (https://pymotw.com/3/) introduces a filtered selection of the standard libary with more examples and a less techincal explanations.
import os
import pprint # pretty print
current = os.getcwd()
os.chdir("/tmp")
# open('x', 'w')
print()
print("files in current folder", os.getcwd())
pprint.pprint(os.listdir("."))
print()
os.chdir(current)
if not os.path.exists("abc"):
print("abc does not exist")
# touch:
open("abc", "w").close()
if os.path.exists("abc"):
os.remove("abc")
print("deleted abc")
files in current folder /private/tmp ['17_scientific_python.ipynb', '07_dictionaries.ipynb', 'MozillaUpdateLock-191289357BF03661', '00_introduction.ipynb', '06_lists_and_tuples.ipynb', '.ICE-unix', 'say_hi.txt', 'say_hi_upper.txt', 'conda', 'powerlog', '11_args_and_kwargs.ipynb', 'data.db', 'blbla.txt', '13_lambda_functions.ipynb', '.s.PGSQL.5432.lock', '03_functions.ipynb', 'ko.9ede98cc.32f0d824.0', 'a', '08_file_io.ipynb', 'httping.dat', '.X11-unix', '05_loops.ipynb', 'boost_interprocess', '18_type_hints_and_data_classes.ipynb', 'com.adobe.acrobat.rna.RdrCefBrowserLock.DC', 'powerline-ipc-501', 'com.adobe.reader.rna.13e2f.1f5', 'com.adobe.reader.rna.facb.1f5', '02_strings.ipynb', 'com.apple.launchd.1zkuMoQBSJ', 'com.adobe.reader.rna.0.1f5.DC', '16_selected_modules_from_the_standard_library.ipynb', '04_if_elif_else.ipynb', 'data.pkl', '14_decorators_and_context_managers.ipynb', '15_object_oriented_programming_introduction.ipynb', 'ko.51c174cb.3542dba8.1', '09_tuple_unpacking_etc.ipynb', 'python_logo.png', '30A0A2F4-CFAD-48B0-B590-4DEF623993BE-vpndownloader', '.s.PGSQL.5432', 'com.adobe.AdobeIPCBroker.ctrl-uweschmitt', '01_basics.ipynb', '10_exceptions.ipynb', '.font-unix', '12_generator_expressions_and_yield.ipynb', 'tmux-501', 'com.apple.launchd.nZxliGqaSs', 'compute.py'] abc does not exist deleted abc
print(os.path.abspath("."))
/private/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/T/tmp.7gVLKvoQ
print(os.path.dirname(os.path.abspath(".")))
print(os.path.basename(os.path.abspath(".")))
print(os.path.join("a", "b", "c.txt"))
/private/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/T tmp.7gVLKvoQ a/b/c.txt
print(os.path.splitext("abc.py"))
('abc', '.py')
if not os.path.exists("/tmp/a/b/c/d"):
os.makedirs("/tmp/a/b/c/d")
Recent Python 3 versions also include the pathlib
module, which makes path manipulations more expressive compared to using os.path
.
import pathlib
here = pathlib.Path(".")
print(here)
print(here.resolve())
print(here.resolve().parent.parent)
print(here.resolve().parent.parent / "xyz")
. /private/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/T/tmp.7gVLKvoQ /private/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn /private/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/xyz
Iterate over files in folders based on "globbing pattern":
import glob
for nb in glob.glob("/private/*/*.ipynb"):
print(nb)
/private/tmp/17_scientific_python.ipynb /private/tmp/07_dictionaries.ipynb /private/tmp/00_introduction.ipynb /private/tmp/06_lists_and_tuples.ipynb /private/tmp/11_args_and_kwargs.ipynb /private/tmp/13_lambda_functions.ipynb /private/tmp/03_functions.ipynb /private/tmp/08_file_io.ipynb /private/tmp/05_loops.ipynb /private/tmp/18_type_hints_and_data_classes.ipynb /private/tmp/02_strings.ipynb /private/tmp/16_selected_modules_from_the_standard_library.ipynb /private/tmp/04_if_elif_else.ipynb /private/tmp/14_decorators_and_context_managers.ipynb /private/tmp/15_object_oriented_programming_introduction.ipynb /private/tmp/09_tuple_unpacking_etc.ipynb /private/tmp/01_basics.ipynb /private/tmp/10_exceptions.ipynb /private/tmp/12_generator_expressions_and_yield.ipynb
# more advanced operations on file system, like recursive
# copying or deletion of folders:
import shutil
shutil.copytree
shutil.rmtree
shutil.copy;
import tempfile
temp_folder = tempfile.mkdtemp()
print(temp_folder)
temp_folder = tempfile.mkdtemp()
print(temp_folder)
/var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/T/tmp4sa1g7do /var/folders/k8/zfp7dvcs1m326gz1brql1tv80000gn/T/tmp7466ydkr
from datetime import datetime
n = datetime.now()
print(type(n))
print(n)
print(n.month, n.hour)
<class 'datetime.datetime'> 2023-02-23 14:39:56.749474 2 14
import time
n = datetime.now()
time.sleep(1)
delta = datetime.now() - n
print(type(delta))
print(delta)
<class 'datetime.timedelta'> 0:00:01.000582
Formatting and parsing data time values:
datetime.strftime
datetime.strptime;
import pickle
complex_data = {0: [1, 2], 1: {2: [1, 2, (3, 4)]}}
bytestream = pickle.dumps(complex_data, protocol=4)
print(bytestream)
b'\x80\x04\x95$\x00\x00\x00\x00\x00\x00\x00}\x94(K\x00]\x94(K\x01K\x02eK\x01}\x94K\x02]\x94(K\x01K\x02K\x03K\x04\x86\x94esu.'
back = pickle.loads(bytestream)
print(back)
print(back == complex_data)
{0: [1, 2], 1: {2: [1, 2, (3, 4)]}} True
pickle.dump
pickle.load
<function _pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=())>
# USE BINARY MODE FOR PICKLING/UNPICKLING ALWAYS !!!!
with open("data.pkl", "wb") as fh:
pickle.dump(complex_data, fh)
print(pickle.load(open("data.pkl", "rb")))
{0: [1, 2], 1: {2: [1, 2, (3, 4)]}}
!cat data.pkl
��$ }�(K ]�(KKeK}�K]�(KKKK��esu.
import sys
print(sys.version_info)
print(sys.executable)
print(sys.platform)
sys.version_info(major=3, minor=10, micro=9, releaselevel='final', serial=0) /Users/uweschmitt/Projects/python-introduction/venv/bin/python3.10 darwin
sqlite3
is a database system without management overhead. A sqlite database is just a plain file.
sqlite3
is not efficient for multi-client access, but very fast (also for large databases) when accessed from a single client, and as such is often used as a application data format. See also https://en.wikipedia.org/wiki/SQLite#Notable_users
import os
import sqlite3
if os.path.exists("data.db"):
os.remove("data.db")
db = sqlite3.connect("data.db")
db.execute("CREATE TABLE points (x REAL, y REAL, z REAL);")
points = [(i, i + 1, i + 2) for i in range(10)]
db.executemany("INSERT INTO points VALUES (?, ?, ?)", points)
db.commit()
query = db.execute("SELECT x, y, z, x + y + z FROM points WHERE x > 3 AND z < 8")
for row in query.fetchall():
print(row)
(4.0, 5.0, 6.0, 15.0) (5.0, 6.0, 7.0, 18.0)
sqlite3
also shines for spatial data and fuzzy text search.
import gzip
import tarfile
import zipfile
import zlib
Use csv
for csv file handling!
import csv
import math
print(math.pi)
print(math.cos(math.atan(1)))
3.141592653589793 0.7071067811865476
Python also supports complex numbers, the complex unit is written as j
:
1j**2
(-1+0j)
import cmath
print(cmath.sqrt(-1))
# exp(pi * i) == -1
print(cmath.exp(math.pi * 1j))
1j (-1+1.2246467991473532e-16j)
The statistics
module offers numerically robust implementations of basic statistics:
import statistics
print(statistics.median(range(12)))
print(statistics.variance(range(12)))
5.5 13
random
offers pseudo random generators for different distributions:
import random
print(random.gauss(mu=1.0, sigma=1.0))
print(random.uniform(2, 3))
1.1427292729234257 2.456483081637054
f = 1.1 + 2.2
print("f is", f)
# supports fractions:
import fractions
print()
print("using fractions")
f = fractions.Fraction(11, 10) + fractions.Fraction(22, 10)
print("f is", f)
print("float(f) is", float(f))
# supports arbitrary precise floats
import decimal
print()
print("using decimal")
f = decimal.Decimal("1.1") + decimal.Decimal("2.2")
print("f is", f)
print("float(f) is", float(f))
f is 3.3000000000000003 using fractions f is 33/10 float(f) is 3.3 using decimal f is 3.3 float(f) is 3.3
A defaultdict
is a dictionary-like data structure with a specified default value for unkown keys.
The signature is defaultdict(function)
where function()
delivers the defaultvalue.
from collections import defaultdict
def get_three():
return 3
d = defaultdict(get_three)
print(d[0])
3
Here are two typical use cases:
# int() results in 0:
int()
0
Thus defaultdict(int)
can be used to simplify counting:
data = "adffjjkjwet"
counter = defaultdict(int)
for c in data:
counter[c] += 1
print(counter.items())
dict_items([('a', 1), ('d', 1), ('f', 2), ('j', 3), ('k', 1), ('w', 1), ('e', 1), ('t', 1)])
And defaultdict(list)
for grouping data:
list()
[]
grouped_values = defaultdict(list)
values = [1, 2, 3, 2, 1, 3, 4]
groups = [0, 1, 1, 0, 1, 1, 0]
for g, v in zip(groups, values):
grouped_values[g].append(v)
print(grouped_values)
for g, values in grouped_values.items():
print("average of group", g, "is", sum(values) / len(values))
defaultdict(<class 'list'>, {0: [1, 2, 4], 1: [2, 3, 1, 3]}) average of group 0 is 2.3333333333333335 average of group 1 is 2.25
The previous example for counting can be simplified further:
from collections import Counter
c = Counter(data)
print(c)
print(c.most_common(1))
Counter({'j': 3, 'f': 2, 'a': 1, 'd': 1, 'k': 1, 'w': 1, 'e': 1, 't': 1}) [('j', 3)]
Python tuple
s are helpful four grouping data, the namedtuple
extends this by assigning names to the elements:
from collections import namedtuple
point = (1, 2, 3)
print(point)
point[0] = 2
(1, 2, 3)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[36], line 5 3 point = (1, 2, 3) 4 print(point) ----> 5 point[0] = 2 TypeError: 'tuple' object does not support item assignment
Point = namedtuple("Point", ["x", "y", "z"])
p = Point(1, 2, 3)
print(p.x)
p = Point(2, 3, 4)
q = p
def set_0(p, value):
return Point(value, p[1], p[2])
q = set_0(p, 7)
print(q)
data = [1, 2, 3]
x = (1, data)
print(x)
1 Point(x=7, y=3, z=4) (1, [1, 2, 3])
x[1].append(3)
print(x)
(1, [1, 2, 3, 3])
Similar to the builtin tuple
type, a namedtuple
is immutable:
p.y = 2
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[39], line 1 ----> 1 p.y = 2 AttributeError: can't set attribute
# only mentioned here
import heapq
import itertools # combinatorics and more
import queue
for perm in itertools.permutations([1, 2, 3]):
print(perm)
(1, 2, 3) (1, 3, 2) (2, 1, 3) (2, 3, 1) (3, 1, 2) (3, 2, 1)
Python variables are references, thus assignment is not copy of underlying data:
data = [1, 2, [3]]
data_copy = data
data_copy.append(4)
print(data)
[1, 2, [3], 4]
is
checks of objects are the same. This is different to ==
which checks if the content is the same.
data_copy is data
True
The copy
module provides shallow and deep copying usiong copy.copy
and copy.deepcopy
:
import copy
data_copy = copy.copy(data)
print(data_copy is data)
print(data_copy[2] is data[2])
False True
data_copy = copy.deepcopy(data)
print(data_copy is data)
print(data_copy[2] is data[2])
False False
data.append(5)
print(data)
print(data_copy)
[1, 2, [3], 4, 5] [1, 2, [3], 4]
data_copy == data
False
import time
# seconds since 1.1.1970:
print(time.time())
1677159598.1549618
def fib(n):
if n < 2:
return 1
return fib(n - 1) + fib(n - 2)
print(fib(10))
89
Number of function calls grows exponentially for this implementation of fibionacci numbers:
calls = 0
def fib(n):
global calls
calls += 1
if n < 2:
return 1
return fib(n - 1) + fib(n - 2)
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=(8, 6))
for n in range(25):
calls = 0
fib(n)
plt.scatter([n], [calls], color="g")
plt.xlabel("n")
plt.ylabel("#calls")
ax = plt.gca()
ax.set_yscale("log")
started = time.time()
print(fib(35))
print(time.time() - started)
14930352 3.2805800437927246
A cache prevents repeated function evaluations for known pairs of (arguments, return value):
import functools
@functools.lru_cache()
def fib_cached(n):
if n < 2:
return 1
return fib_cached(n - 1) + fib_cached(n - 2)
started = time.time()
print(fib_cached(36))
print(time.time() - started)
24157817 5.2928924560546875e-05
print(fib_cached.cache_info())
CacheInfo(hits=34, misses=37, maxsize=128, currsize=37)
LRU
means "last recent update" which means that cache entries are discared based on their last usage.
The default lru_cache
holds up to 128 entries. This can me modified another numerical value:
@functools.lru_cache(maxsize=2)
def fib_cached(n):
if n < 2:
return 1
return fib_cached(n - 1) + fib_cached(n - 2)
started = time.time()
print(fib_cached(36))
print(time.time() - started)
print(fib_cached.cache_info())
24157817 0.03538823127746582 CacheInfo(hits=59863, misses=287964, maxsize=2, currsize=2)
Comment: if you use maxsize=None
the cache is unlimited, but this could use up all your memory !
This is all in memory caching and thus is not persisent between notebook kernels or runs from the command line.
Alternative: joblib
(external lib) can cache data on disk.
Alternative: use an better algorithm:
def fib(n):
a, b = 1, 1
for i in range(2, n + 1):
a, b = b, a + b
return b
for i in range(5):
print(fib(i))
1 1 2 3 5
One can also compute all numbers up to $n$ efficiently:
def fibs(n):
numbers = [1, 1]
while len(numbers) <= n:
numbers.append(numbers[-1] + numbers[-2])
return numbers[:n]
print(fibs(100))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853, 72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264, 806515533049393, 1304969544928657, 2111485077978050, 3416454622906707, 5527939700884757, 8944394323791464, 14472334024676221, 23416728348467685, 37889062373143906, 61305790721611591, 99194853094755497, 160500643816367088, 259695496911122585, 420196140727489673, 679891637638612258, 1100087778366101931, 1779979416004714189, 2880067194370816120, 4660046610375530309, 7540113804746346429, 12200160415121876738, 19740274219868223167, 31940434634990099905, 51680708854858323072, 83621143489848422977, 135301852344706746049, 218922995834555169026, 354224848179261915075]
Regular expressions are helpful for parsing complex strings.
Here we look for a sequence stating with a
, followed by 0 or more digits, and finally terminated by a second a
:
import re
m = re.findall("a[b1]", "xyza12345abc")
print(m)
['a1', 'ab']
import re
m = re.findall("a[0-9]a", "xyza12345abc")
m
[]
m = re.search("a([0-9]*)a", "xyza12345abca111ax")
print(m.group(0))
print(m.group(1))
a12345a 12345
m = re.search("a([0-9]*)a", "xyz12345abc111ax")
print(m)
None
More about regular expressions: https://developers.google.com/edu/python/regular-expressions and https://stackabuse.com/introduction-to-regular-expressions-in-python/
To make this work in a notebook on Mac (which I used when writing this script) is to write the code I want to run on multiple cores to a file first, the %%file
below is a so-called cell-magic (specific to jupyter, not part of Python
) which will write the cell content to a file:
%%file compute.py
import os
import time
def compute(argument):
started = time.time()
print("process", os.getpid(), "starts computation for argument", argument)
time.sleep(argument)
print("process", os.getpid(), "finished computation for argument", argument)
return (os.getpid(), argument, time.time() - started)
Writing compute.py
import time
from concurrent.futures import ProcessPoolExecutor
from compute import compute
use_cores = 3
started = time.time()
with ProcessPoolExecutor(use_cores) as p_pool:
for worker_id, argument, needed in p_pool.map(compute, (3, 1, 2, 1)):
print(
f"worker {worker_id} got argument {argument} and needed {needed:.2f} seconds"
)
print("overall time {:.2f} seconds".format(time.time() - started))
worker 31634 got argument 3 and needed 3.01 seconds worker 31635 got argument 1 and needed 1.00 seconds worker 31636 got argument 2 and needed 2.00 seconds worker 31635 got argument 1 and needed 1.00 seconds process 31635 starts computation for argument 1 process 31635 finished computation for argument 1 process 31635 starts computation for argument 1 process 31635 finished computation for argument 1 process 31636 starts computation for argument 2 process 31636 finished computation for argument 2 process 31634 starts computation for argument 3 process 31634 finished computation for argument 3 overall time 3.09 seconds
You can see that the 9 functions evaluations where distributed to 7 workers such that some workers performed multiple function evaluations.
In total the first evaluation needed longest and dominates the overall runtime.
The easiest way to call external executables is os.system
. You don't see generated output, the return value is 0 for successful execution.
The following example assumes that you work on linux, so you should adapt it if you work on Windows:
print(os.system("ls -al"))
total 20592 drwx------ 46 uweschmitt staff 1472 Feb 23 14:40 . drwx------@ 7524 uweschmitt staff 240768 Feb 23 14:39 .. -rw-r--r-- 1 uweschmitt staff 593693 Feb 23 14:38 00_introduction.html -rw-r--r-- 1 uweschmitt staff 8623 Feb 23 14:38 00_introduction.ipynb -rw-r--r-- 1 uweschmitt staff 640208 Feb 23 14:38 01_basics.html -rw-r--r-- 1 uweschmitt staff 15373 Feb 23 14:38 01_basics.ipynb -rw-r--r-- 1 uweschmitt staff 643500 Feb 23 14:38 02_strings.html -rw-r--r-- 1 uweschmitt staff 15345 Feb 23 14:38 02_strings.ipynb -rw-r--r-- 1 uweschmitt staff 624293 Feb 23 14:38 03_functions.html -rw-r--r-- 1 uweschmitt staff 12706 Feb 23 14:38 03_functions.ipynb -rw-r--r-- 1 uweschmitt staff 606278 Feb 23 14:38 04_if_elif_else.html -rw-r--r-- 1 uweschmitt staff 8342 Feb 23 14:38 04_if_elif_else.ipynb -rw-r--r-- 1 uweschmitt staff 622855 Feb 23 14:39 05_loops.html -rw-r--r-- 1 uweschmitt sta0 ff 11725 Feb 23 14:39 05_loops.ipynb -rw-r--r-- 1 uweschmitt staff 639430 Feb 23 14:39 06_lists_and_tuples.html -rw-r--r-- 1 uweschmitt staff 13823 Feb 23 14:39 06_lists_and_tuples.ipynb -rw-r--r-- 1 uweschmitt staff 631449 Feb 23 14:39 07_dictionaries.html -rw-r--r-- 1 uweschmitt staff 13939 Feb 23 14:39 07_dictionaries.ipynb -rw-r--r-- 1 uweschmitt staff 615602 Feb 23 14:39 08_file_io.html -rw-r--r-- 1 uweschmitt staff 10309 Feb 23 14:39 08_file_io.ipynb -rw-r--r-- 1 uweschmitt staff 628384 Feb 23 14:39 09_tuple_unpacking_etc.html -rw-r--r-- 1 uweschmitt staff 10448 Feb 23 14:39 09_tuple_unpacking_etc.ipynb -rw-r--r-- 1 uweschmitt staff 632036 Feb 23 14:39 10_exceptions.html -rw-r--r-- 1 uweschmitt staff 13844 Feb 23 14:39 10_exceptions.ipynb -rw-r--r-- 1 uweschmitt staff 600543 Feb 23 14:39 11_args_and_kwargs.html -rw-r--r-- 1 uweschmitt staff 5238 Feb 23 14:39 11_args_and_kwargs.ipynb -rw-r--r-- 1 uweschmitt staff 613135 Feb 23 14:39 12_generator_expressions_and_yield.html -rw-r--r-- 1 uweschmitt staff 7727 Feb 23 14:39 12_generator_expressions_and_yield.ipynb -rw-r--r-- 1 uweschmitt staff 586833 Feb 23 14:39 13_lambda_functions.html -rw-r--r-- 1 uweschmitt staff 2440 Feb 23 14:39 13_lambda_functions.ipynb -rw-r--r-- 1 uweschmitt staff 615798 Feb 23 14:39 14_decorators_and_context_managers.html -rw-r--r-- 1 uweschmitt staff 10353 Feb 23 14:39 14_decorators_and_context_managers.ipynb -rw-r--r-- 1 uweschmitt staff 707943 Feb 23 14:39 15_object_oriented_programming_introduction.html -rw-r--r-- 1 uweschmitt staff 40600 Feb 23 14:39 15_object_oriented_programming_introduction.ipynb -rw-r--r-- 1 uweschmitt staff 0 Feb 23 14:39 16_selected_modules_from_the_standard_library.html -rw-r--r-- 1 uweschmitt staff 29712 Feb 23 14:39 16_selected_modules_from_the_standard_library.ipynb -rw-r--r-- 1 uweschmitt staff 0 Feb 23 14:39 blbla.txt -rw-r--r-- 1 uweschmitt staff 319 Feb 23 14:40 compute.py -rw-r--r-- 1 uweschmitt staff 3055 Feb 23 14:38 custom.html drwxr-xr-x 4 uweschmitt staff 128 Feb 23 14:38 data -rw-r--r-- 1 uweschmitt staff 8192 Feb 23 14:39 data.db -rw-r--r-- 1 uweschmitt staff 47 Feb 23 14:39 data.pkl drwxr-xr-x 10 uweschmitt staff 320 Feb 23 14:38 images -rw-r--r-- 1 uweschmitt staff 6 Feb 23 14:39 say_hi.txt -rw-r--r-- 1 uweschmitt staff 6 Feb 23 14:39 say_hi_upper.txt -rw-r--r-- 1 uweschmitt staff 16 Feb 23 14:39 test2.csv
The subprocess
module is more versatile and allows finer grained access to stdin and / or stdout of the executable:
import subprocess
p = subprocess.check_output("ls -al *.ipynb", shell=True)
print(str(p, "utf-8"))
-rw-r--r-- 1 uweschmitt staff 8623 Feb 23 14:38 00_introduction.ipynb -rw-r--r-- 1 uweschmitt staff 15373 Feb 23 14:38 01_basics.ipynb -rw-r--r-- 1 uweschmitt staff 15345 Feb 23 14:38 02_strings.ipynb -rw-r--r-- 1 uweschmitt staff 12706 Feb 23 14:38 03_functions.ipynb -rw-r--r-- 1 uweschmitt staff 8342 Feb 23 14:38 04_if_elif_else.ipynb -rw-r--r-- 1 uweschmitt staff 11725 Feb 23 14:39 05_loops.ipynb -rw-r--r-- 1 uweschmitt staff 13823 Feb 23 14:39 06_lists_and_tuples.ipynb -rw-r--r-- 1 uweschmitt staff 13939 Feb 23 14:39 07_dictionaries.ipynb -rw-r--r-- 1 uweschmitt staff 10309 Feb 23 14:39 08_file_io.ipynb -rw-r--r-- 1 uweschmitt staff 10448 Feb 23 14:39 09_tuple_unpacking_etc.ipynb -rw-r--r-- 1 uweschmitt staff 13844 Feb 23 14:39 10_exceptions.ipynb -rw-r--r-- 1 uweschmitt staff 5238 Feb 23 14:39 11_args_and_kwargs.ipynb -rw-r--r-- 1 uweschmitt staff 7727 Feb 23 14:39 12_generator_expressions_and_yield.ipynb -rw-r--r-- 1 uweschmitt staff 2440 Feb 23 14:39 13_lambda_functions.ipynb -rw-r--r-- 1 uweschmitt staff 10353 Feb 23 14:39 14_decorators_and_context_managers.ipynb -rw-r--r-- 1 uweschmitt staff 40600 Feb 23 14:39 15_object_oriented_programming_introduction.ipynb -rw-r--r-- 1 uweschmitt staff 29712 Feb 23 14:39 16_selected_modules_from_the_standard_library.ipynb
Here we start a Python process (-i
is crucial to make this work), and remotely "enter" a line of code and capture the output.
Such code is fragile and prone to hanging. Just remove the indicated line and you will see that the p.stdout.readline()
call hangs.
This does not mean, that this approach is not recommended, but you have to think about a communication protocol including error handling.
from urllib import request
response = request.urlopen("https://www.python.org/static/img/python-logo@2x.png")
with open("python_logo.png", "wb") as fh:
fh.write(response.read())
# this is jupyter notebook specific command and not supported
# by Python itself:
!ls -l python_logo.png
-rw-r--r-- 1 uweschmitt staff 15770 Feb 23 14:40 python_logo.png
Note: urllib
is not easy to use in more complicated cases, like authentification, etc. In such cases install and use the requests library