name: about-me layout: false # About Me I... - am **Syamala Umamaheswaran** - work for **Volkswagen Digital:Lab Berlin** as a Software Engineer - like a good discussion around **Test Driven Development**, **Pair Programming**, **Java vs Kotlin**, **Software architectures**, **OAuth2**, **Spring Framework** ... - occasionally blog @ https://dev.to/shyamala_u - am fairly active in twitter @shyamala_u --- name: inverse layout: true class: center, middle, inverse --- #My Rendezvous with Python  https://shyamz-22.github.io/py-rendezvous/ --- name: cycle layout: false .left-column[ ## cycle ] .right-column[ Return elements from the iterable until it is exhausted. Then repeat the sequence indefinitely. ```python clocks = ['π', 'π', 'π', 'π', 'π', 'π', 'π'] `clock = cycle(clocks)` msg = 'Loading... ' for i in range(10): print('\r' + msg + next(clock), end='') sleep(1) ``` Output: ```bash Loading... π ``` ] .footnote[https://docs.python.org/3/library/itertools.html#itertools.cycle] ??? how it is a great tool, when writing command line tools. --- name: count layout: false .left-column[ ## count ] .right-column[ Counting the occurence of the given value in an iterable. ```python colours = ['red', 'yellow', 'orange', 'red', 'white'] random_string = 'thisisarandomstring' red_count = `colours.count('red')` i_count = `random_string.count("i")` print(f'red appears "{red_count}" times') print(f'i appears "{i_count}" times') ``` Output: ```bash red appears "2" times i appears "3" times ``` Writing count on the list is more elegant than writing `Collections.frequency(colors, "red")` in Java. ] .footnote[https://docs.python.org/3/library/itertools.html#itertools.cycle] --- name: counter layout: false .left-column[ ## Counter ] .right-column[ While `count` is for specific value in the list. If you want to know running counts of all values in an iterable, ```python from collections import Counter word = 'pneumonoultramicroscopicsilicovolcanoconiosis' print('Word: ', word) c = Counter(word) print('counter: ', c) print('top 5: ', c.most_common(5)) ``` Output: ```bash Word: pneumonoultramicroscopicsilicovolcanoconiosis counter: Counter({'o': 9, 'i': 6, 'c': 6, 'n': 4, 's': 4, 'l': 3, 'p': 2, 'u': 2, 'm': 2, 'r': 2, 'a': 2, 'e': 1, 't': 1, 'v': 1}) top 5: [('o', 9), ('i', 6), ('c', 6), ('n', 4), ('s', 4)] ``` ] .footnote[https://docs.python.org/3/library/collections.html#counter-objects] --- name: data-classes layout: false .left-column[ ## Data Classes ] .right-column[ DataClasses are simply containers of data. They are normal Python classes with some boilerplate code implemented already. - You can make data classes immutable. - Type Hints are mandatory, even though they are not enforced in runtime. ### But repeat after me: Type Hints are good and we stick to them!! ] ??? - dunder - Double under - (.__init__(), .__repr__(), and .__eq__() are implemented already). - Emphasize on the immutability --- .left-column[ ## Data Classes ] .right-column[ ```python from dataclasses import dataclass @dataclass(init=True, repr=True, eq=True, order=False, frozen=True, # default is false unsafe_hash=False) class InventoryItem: name: str unit_price: float quantity_on_hand: int = 0 ``` ```python item_cola_a = InventoryItem(name='cola', unit_price=20.0, quantity_on_hand=10) item_cola_b = InventoryItem(name='cola', unit_price=20.0, quantity_on_hand=10) print('Item: ', item_cola_b) print('Equal? ', item_cola_a == item_cola_b) ``` Output: ```bash Item: InventoryItem(name='cola', unit_price=20.0, quantity_on_hand=10) Equal? True ``` ] .footnote[https://docs.python.org/3/library/dataclasses.html#module-dataclasses] ??? - Talk about the importance of Type Hints and Named Parameters For Integrity - type hints, Readability - named parameters. Simplicity - less boiler plate code --- name: decorators .left-column[ ## Decorators ] .right-column[ Decorators wraps a funtion, Modifying the behavior ```python from functools import wraps from flask import Flask, request, Response app = Flask(__name__) def requires_authentication(f): @wraps(f) def decorated(): auth = request.headers.get('Authorization') if not auth or auth != 'Bearer my-secret-api-key': return Response('Not Authorized', 401, {'WWW-Authenticate': 'Bearer realm="Bearer"'}) return f() return decorated @app.route('/') @requires_authentication def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run() ``` ] ??? Functions are just like any other objects in Python. Decorators are Functions that takes in a function as input parameter and returns another function. Makes code readable, at the same time the implementation is explicit. I like that I could do this that is not part of a framework. --- .left-column[ ## Decorators ] .right-column[ Output: ```bash > curl -H 'Authorization: Bearer my-secret-api-key' \ http://127.0.0.1:5000/ Hello, World! ``` ``` > curl http://127.0.0.1:5000/ Not Authorized ``` ] .footnote[https://realpython.com/primer-on-python-decorators/] --- name: graceful-shutdown .left-column[ ## Graceful Shutdown ### Why ] .right-column[ When application receives a `SIGTERM`, - Server should stop receiving new requests - Finish processing the ongoing requests - Release any resources - Exit ] ??? The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL, this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate. --- .left-column[ ## Graceful Shutdown ### Why ### Python ] .right-column[ If you use [gunicorn](http://docs.gunicorn.org/en/stable/index.html) as a server, it will handle the shutdown for you, by default it waits for 30 seconds before it kills an open connection. You donβt have to handle the SIGTERM within your application. ``` > pipenv install gunicorn > gunicorn "src:app() --graceful-timeout 10" ``` ] --- .left-column[ ## Graceful Shutdown ### Why ### Python ### Go ] .right-column[ ```go func main() { mux := http.NewServeMux() mux.HandleFunc("/", random) server := http.Server{ Addr: ":8080", Handler: mux, } go func() { server.ListenAndServe() }() // here the magic happens osSignals := make(chan os.Signal, 1) // subscribe to SIGTERM signal.Notify(osSignals, syscall.SIGTERM) select { case <-osSignals: log.Print("caught signal, shutting down") // create timeout const timeout = 10 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() // wait before dying, context will release resources server.Shutdown(ctx) } } ``` ] --- .left-column[ ## Graceful Shutdown ### Why ### Python ### Go ### Java + Tomcat + Spring ] .right-column[ A small peek into graceful shutdown in Java + Tomcat + Spring Framework ```Java @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean public GracefulShutdown gracefulShutdown() { return new GracefulShutdown(); } @Bean public WebServerFactoryCustomizer tomcatCustomizer(GracefulShutdown gracefulShutdown) { return factory -> { if (factory instanceof TomcatServletWebServerFactory) { ((TomcatServletWebServerFactory) factory) .addConnectorCustomizers(gracefulShutdown); } }; } ``` To Be Continued ... ] --- .left-column[ ## Graceful Shutdown ### Why ### Python ### Go ### Java + Tomcat + Spring ] .right-column[ ```Java private static class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener
{ private static final Logger log = LoggerFactory.getLogger(GracefulShutdown.class); private volatile Connector connector; @Override public void customize(Connector connector) { this.connector = connector; } @Override public void onApplicationEvent(ContextClosedEvent event) { log.warn("received ContextClosedEvent"); Executor executor = this.connector.getProtocolHandler().getExecutor(); if (executor instanceof ThreadPoolExecutor) { try { ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor; threadPoolExecutor.shutdown(); if (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)) { log.warn("Tomcat thread pool did not shut down gracefully within " + "10 seconds. Proceeding with forceful shutdown"); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } } ``` ] --- template: inverse name: zen # [The Zen of Python](https://www.python.org/dev/peps/pep-0020/#id3) --- name: zen-values class: middle A collection of 19 "guiding principles" that influence the design of the Python programming language. ```python > python3 -m this The Zen of Python, by Tim Peters `Beautiful is better than ugly.` `Explicit is better than implicit.` `Simple is better than complex.` Complex is better than complicated. Flat is better than nested. Sparse is better than dense. `Readability counts.`` Special cases aren't special enough to break the rules. Although practicality beats purity. `Errors should never pass silently.` Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. `If the implementation is hard to explain, it's a bad idea.` If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! ``` --- template: inverse name: thank-you #Thank you!  https://shyamz-22.github.io/py-rendezvous Slides By [Remark](https://remarkjs.com)