{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to Python " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Code Optimization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "References: \n", "http://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html \n", "https://numba.pydata.org/ \n", "https://gist.github.com/jfpuget/b53f1e15a37aba5944ad " ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "import random\n", "import time\n", "import glob\n", "import os\n", "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's create a recursive Fibonacci function and test with diferent parameters:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def fib(n):\n", " if n < 2:\n", " return 1\n", " return fib(n-1) + fib(n-2)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.12 ms ± 50.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit fib(20)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "262 ms ± 8.07 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%timeit fib(30)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.13 s ± 15 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%timeit fib(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Now, let's compile with Cython: \n", "\n", "+ pip3 install Cython" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "%load_ext Cython" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "\n", "def fib_cython(n):\n", " if n < 2:\n", " return 1\n", " return fib_cython(n-1) + fib_cython(n-2)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "649 µs ± 7.94 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit fib_cython(20)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "78.9 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "%timeit fib_cython(30)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "347 ms ± 8.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%timeit fib_cython(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos melhorar ainda mais compilando as variáveis estaticamente. \n", "A função deve ser declarada com \"cpdef\" ao invés de def\". Dessa forma, podemos usar os [tipos do C](https://www.tutorialspoint.com/cprogramming/c_data_types.htm) como parâmetros da função: " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "\n", "cpdef long fib_cython_type(long n):\n", " if n < 2:\n", " return 1\n", " return fib_cython_type(n-1) + fib_cython_type(n-2)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "18.1 µs ± 592 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit fib_cython_type(20)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.19 ms ± 69.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit fib_cython_type(30)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9.35 ms ± 303 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit fib_cython_type(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma outra abordagem é permitindo que os resultados sejam guardados em _cache_: \n", "Dessa forma podemos manter a precisão arbitrária das variáveis do Python, sem recorrer aos [tipos estáticos do C](https://notes-on-cython.readthedocs.io/en/latest/function_declarations.html)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "from functools import lru_cache as cache #Python3" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "@cache(maxsize=None)\n", "def fib_cache(n):\n", " if n < 2:\n", " return 1\n", " return fib_cache(n-1) + fib_cache(n-2)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "67.1 ns ± 1.27 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_cache(20)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "66.1 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_cache(30)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "66 ns ± 0.93 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_cache(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma outra maneira de emular o cache seria realizando uma modificação no algoritmo:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def fib_seq(n):\n", " if n < 2:\n", " return 1\n", " a,b = 1,0\n", " for i in range(n-1):\n", " a, b = a + b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "965 ns ± 22.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq(20)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.37 µs ± 37.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq(30)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.48 µs ± 47.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos compilar esta nova função com e sem a utilização de tipagem estática: " ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "\n", "def fib_seq_cython(n):\n", " if n < 2:\n", " return 1\n", " a,b = 1,0\n", " for i in range(n-1):\n", " a, b = a + b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "535 ns ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython(20)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "771 ns ± 21.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython(30)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "800 ns ± 14.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython(33)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "\n", "cpdef long fib_seq_cython_type(long n):\n", " if n < 2:\n", " return 1\n", " cdef long a,b\n", " a,b = 1,0\n", " for i in range(n-1):\n", " a, b = a+b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "64 ns ± 3.41 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython_type(20)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "67.2 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython_type(30)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "69.6 ns ± 0.903 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_cython_type(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos usar uma ferramenta chamada Numba, que é um just-in-time (jit) compiler:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "from numba import jit" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def fib_numba(n):\n", " if n < 2:\n", " return 1\n", " return fib_numba(n-1) + fib_numba(n-2)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "74 µs ± 2.64 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n" ] } ], "source": [ "%timeit fib_numba(20)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9.18 ms ± 368 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit fib_numba(30)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "38.2 ms ± 964 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "%timeit fib_numba(33\n", "\n", "The following iterative sequence is defined for the set of positive integers:\n", "\n", "n → n/2 (n is even)\n", "n → 3n + 1 (n is odd)\n", "\n", "Using the rule above and starting with 13, we generate the following sequence:\n", "13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1\n", "\n", "It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.\n", "\n", "Which starting number, under one million, produces the longest chain?\n", "\n", "NOTE: Once the chain starts the terms are allowed to go above one million.\n", ")" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def fib_seq_numba(n):\n", " if n < 2:\n", " return 1\n", " a,b = 1,0\n", " for i in range(n-1):\n", " a, b = a + b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "194 ns ± 10.5 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_numba(20)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "203 ns ± 3.61 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_numba(30)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "194 ns ± 10.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit fib_seq_numba(33)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Segundo exemplo: \n", "Algoritmo de ordenação Quick Sort " ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "def qsort_kernel(a, lo, hi):\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a\n", "\n", "def benchmark_qsort():\n", " lst = [random.random() for i in range(1,5000)]\n", " qsort_kernel(lst, 0, len(lst)-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Usando Numba:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def qsort_kernel_numba(a, lo, hi):\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel_numba(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a\n", "\n", "def benchmark_qsort_numba():\n", " lst = [random.random() for i in range(1,5000)]\n", " qsort_kernel_numba(lst, 0, len(lst)-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numba e Numpy:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def qsort_kernel_numba_numpy(a, lo, hi):\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel_numba_numpy(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a\n", "\n", "def benchmark_qsort_numba_numpy():\n", " lst = np.random.rand(5000)\n", " qsort_kernel_numba(lst, 0, len(lst)-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Usando Numpy e Cython: " ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "import numpy as np\n", "import cython\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "cdef double[:] qsort_kernel_cython_numpy_type(double[:] a, long lo, long hi):\n", " cdef: \n", " long i, j\n", " double pivot\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel_cython_numpy_type(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a\n", "\n", "def benchmark_qsort_numpy_cython():\n", " lst = np.random.rand(5000)\n", " qsort_kernel_cython_numpy_type(lst, 0, len(lst)-1)\n", "\n", "def benchmark_sort_numpy():\n", " lst = np.random.rand(5000)\n", " np.sort(lst)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9.32 ms ± 103 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "7.73 ms ± 414 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "414 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n", "468 µs ± 20.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n", "290 µs ± 9.35 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit benchmark_qsort()\n", "%timeit benchmark_qsort_numba()\n", "%timeit benchmark_qsort_numba_numpy()\n", "%timeit benchmark_qsort_numpy_cython()\n", "%timeit benchmark_sort_numpy()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multithreading" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Módulo [Threading](https://www.tutorialspoint.com/python3/python_multithreading.htm) " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import threading" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "exitFlag = 0" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class myThread(threading.Thread):\n", " def __init__(self, threadID, name, counter, delay):\n", " threading.Thread.__init__(self)\n", " self.threadID = threadID\n", " self.name = name\n", " self.counter = counter\n", " self.delay = delay\n", " \n", " def run(self):\n", " print (\"Starting {}...\\n \".format(self.name))\n", " print_time(self.name, self.counter, self.delay)\n", " print (\"Exiting {}... \\n \".format(self.name))\n", "\n", "def print_time(threadName, counter, delay):\n", " while counter:\n", " if exitFlag:\n", " threadName.exit()\n", " time.sleep(delay)\n", " print (\"{}: {}\\n\".format(threadName, time.ctime(time.time())))\n", " counter -= 1" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Create new threads\n", "thread1 = myThread(1, \"Thread-1\", 5, 1)\n", "thread2 = myThread(2, \"Thread-2\", 5, 2)\n", "thread3 = myThread(3, \"Thread-3\", 5, 2)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Starting Thread-1...\n", " \n", "Starting Thread-2...\n", " \n", "Starting Thread-3...\n", " \n", "Thread-1: Mon Oct 22 15:49:06 2018\n", "\n", "Thread-1: Mon Oct 22 15:49:07 2018\n", "Thread-2: Mon Oct 22 15:49:07 2018\n", "\n", "\n", "Thread-3: Mon Oct 22 15:49:07 2018\n", "\n", "Thread-1: Mon Oct 22 15:49:08 2018\n", "\n", "Thread-3: Mon Oct 22 15:49:09 2018\n", "\n", "Thread-2: Mon Oct 22 15:49:09 2018\n", "Thread-1: Mon Oct 22 15:49:09 2018\n", "\n", "\n", "Thread-1: Mon Oct 22 15:49:10 2018\n", "\n", "Exiting Thread-1... \n", " \n", "Thread-3: Mon Oct 22 15:49:11 2018\n", "\n", "Thread-2: Mon Oct 22 15:49:11 2018\n", "\n", "Thread-3: Mon Oct 22 15:49:13 2018\n", "\n", "Thread-2: Mon Oct 22 15:49:13 2018\n", "\n", "Thread-3: Mon Oct 22 15:49:15 2018\n", "\n", "Exiting Thread-3... \n", " \n", "Thread-2: Mon Oct 22 15:49:15 2018\n", "\n", "Exiting Thread-2... \n", " \n", "Exiting Main Thread\n" ] } ], "source": [ "# Start new Threads\n", "thread1.start() #chama o método run\n", "thread2.start()\n", "thread3.start()\n", "thread1.join() #aguarda que o thread termine\n", "thread2.join()\n", "thread3.join()\n", "print (\"Exiting Main Thread\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Módulo [Multiprocessing](https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "main line\n", "module name: __main__\n", "parent process: 56048\n", "process id: 57151\n", "function f\n", "module name: __main__\n", "parent process: 57151\n", "process id: 76230\n", "hello bob\n" ] } ], "source": [ "from multiprocessing import Process\n", "import os\n", "\n", "def info(title):\n", " print(title)\n", " print('module name:', __name__)\n", " print('parent process:', os.getppid())\n", " print('process id:', os.getpid())\n", "\n", "def f(name):\n", " info('function f')\n", " print('hello', name)\n", "\n", "if __name__ == '__main__':\n", " info('main line')\n", " p = Process(target=f, args=('bob',))\n", " p.start()\n", " p.join()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Módulo [Concurrent futures](https://docs.python.org/3/library/concurrent.futures.html)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "import concurrent.futures\n", "import urllib.request" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "112272535095293 is prime: True\n", "112582705942171 is prime: True\n", "112272535095293 is prime: True\n", "115280095190773 is prime: True\n", "115797848077099 is prime: True\n", "1099726899285419 is prime: False\n" ] } ], "source": [ "PRIMES = [\n", " 112272535095293,\n", " 112582705942171,\n", " 112272535095293,\n", " 115280095190773,\n", " 115797848077099,\n", " 1099726899285419]\n", "\n", "def is_prime(n):\n", " if n % 2 == 0:\n", " return False\n", " sqrt_n = int(math.floor(math.sqrt(n)))\n", " for i in range(3, sqrt_n + 1, 2):\n", " if n % i == 0:\n", " return False\n", " return True\n", "\n", "def main():\n", " with concurrent.futures.ProcessPoolExecutor() as executor:\n", " for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):\n", " print('%d is prime: %s' % (number, prime))\n", "\n", "if __name__ == '__main__':\n", " main()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "'http://www.oglobo.com/' page is 134590 bytes\n", "'http://europe.wsj.com/' page is 994081 bytes\n", "'http://www.cnn.com/' page is 1723318 bytes\n", "'http://www.foxnews.com/' page is 230195 bytes\n", "'http://www.bbc.co.uk/' page is 305605 bytes\n" ] } ], "source": [ "URLS = ['http://www.foxnews.com/',\n", " 'http://www.cnn.com/',\n", " 'http://europe.wsj.com/',\n", " 'http://www.bbc.co.uk/',\n", " 'http://www.oglobo.com/']\n", "\n", "# Retrieve a single page and report the URL and contents\n", "def load_url(url, timeout):\n", " with urllib.request.urlopen(url, timeout=timeout) as conn:\n", " return conn.read()\n", "\n", "# We can use a with statement to ensure threads are cleaned up promptly\n", "with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:\n", " # Start the load operations and mark each future with its URL\n", " future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}\n", " for future in concurrent.futures.as_completed(future_to_url):\n", " url = future_to_url[future]\n", " try:\n", " data = future.result()\n", " except Exception as exc:\n", " print('%r generated an exception: %s' % (url, exc))\n", " else:\n", " print('%r page is %d bytes' % (url, len(data)))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }