View
4
Download
0
Category
Preview:
Citation preview
CIS 192: Lecture 12Deploying Apps and Concurrency
Lili Dworkin
University of Pennsylvania
Good Question from Way Back
I All HTTP requests have 1) URL, 2) headers, 3) body
I GET requests: parameters sent in URL
I POST requests: parameters sent in body
Can GET requests have a body?StackOverflow’s response: “Yes, you can send a request body withGET but it should not have any meaning. If you give it meaning byparsing it on the server and changing your response based on itscontents you’re violating the HTTP/1.1 spec.”
Good Question from Last Week
What is the difference between jsonify and json.dumps?
def jsonify(*args, **kwargs):
if __debug__:
_assert_have_json()
return current_app.response_class(json.dumps(dict(*
args, **kwargs), indent=None if request.is_xhr else
2), mimetype='application/json')
I jsonify returns a Response object
I jsonify automatically sets content-type header
I jsonify also sets the indentation
Review
Find a partner!
Deploying Apps
I We’ve been running Flask apps locally on a builtindevelopment server
I When you’re ready to go public, you need to deploy to aproduction server
I Easiest option: use one hosted by someone else!
I We’ll use Heroku, a platform as a service (PaaS) that makesit easy to deploy apps in a variety of languages
Heroku
Prerequisites:
I Virtualenv (creates standalone Python environments)I Heroku toolbox
I Heroku command-line clientI Git (for version control and pushing to Heroku)
Virtualenv
I Allows us to create a virtual Python environment
I Unique, isolated environment for each project
I Use case: different versions of packages for different projects
Virtualenv
How to use it?
prompt$ pip install virtualenv
Now navigate to your project directory:
prompt$ virtualenv --no-site-packages venv
prompt$ source venv/bin/activate
(<name>)prompt$ pip install Flask gunicorn
(<name>)prompt$ deactivate
prompt%
Heroku Toolbox
Once you make a Heroku account, install the Heroku toolbox.Then login:
prompt$ heroku login
Enter your Heroku credentials.
Email: lilidworkin@gmail.com
Password:
Authentication successful.
Procfile
I Use a Procfile to declare what command should be executedto start server
I One might hope to write “web: python hello.py”
I Instead: “web: gunicorn hello:app”
Flask
I Heroku recognizes Python applications by the existence of arequirements.txt file
I Used to specify the required external modules
I prompt% pip freeze > requirements.txt
I Now anyone can install our dependencies by using pip
install -r requirements.txt
Git
Create a new git repository and save our changes:
prompt$ git init
prompt$ echo venv > .gitignore
prompt$ git add .
prompt$ git commit -m "init"
Deploy
Push the application’s repository to Heroku:
prompt% heroku create
Creating stormy-sands-4409...
http://stormy-sands-4409.herokuapp.com/
Git remote heroku added
prompt% git push heroku master
Concurrency
I A process is a running programI Heavy weightI Separate address spacesI Interact through inter-process communication mechanisms
I A process can have multiple threads which allow it to doseveral things at once
I Light weightI Share the same address spaceI Can interact via shared memory
Threads
I Each thread has its own local state
I All threads share the same global state
I In Python, support is provided by the thread (lower level)and threading (higher level) modules
I Python threads are pre-emptive – may be interrupted atarbitrary times
Threading Module
I Create an instance of a Thread objectI Provide a callable object, i.e. function or method
I What does this mean?I Magic method __call__ is defined!
I Provide a tuple of arguments
I To start a thread object executing, invoke start()
Threads
>>> from threading import Thread
>>> def add(x,y):
... print x+y
...
>>> thread = Thread(target=add, args=(5,6))
>>> thread.start()
11
Ok, but one thread isn’t very interesting ... let’s take a look atbasic_threads.py.
Threads
I How to explain the behavior we just saw?
I The “main” thread (our top-level program) finished before theother threads
I We should use join() – when called on a thread object T,this will cause the calling thread (typically “main”) to blockuntil T finishes
Practical Example
I When to use threads in the “real world”?
I One use case: HTTP requests!
I web.py
Problems with Threads
I What happens when a thread gets interrupted in the middleof modifying shared memory?
I threads.py
I The line var[0] += 1 does not execute atomicallyI Thread first has to read var[0]I Then compute var[0] + 1I Then set var[0] to what it just computed
I The thread could be interrupted between any of those actions,and var[0] could be changed without it knowing
Locks
I In order to use shared state, we need to prevent threads fromstepping all over each other
I Mutual exclusion refers to making sure that only some numberof threads (often just 1) are doing something at the same time
I Multiple ways to do this in Python – we will use the Lock class
Locks
lock = Lock()
def inc_var():
lock.acquire()
var[0] += 1
lock.release()
Locks
I Can use with statements with locks!
I Then acquire() and release() get called automatically
lock = Lock()
def inc_var():
with lock:
var[0] += 1
Dining Philosophers
I Between each pair of philosophersis a single chopstick
I Philosophers alternate betweenthinking and eating
I Before eating, first take leftchopstick, then take right
I What if every philosopher takes leftchopstick at the same time?
Global Interpreter Lock (GIL)
The Unwritten Rules of Python:
1. You do not talk about the GIL.
2. You do NOT talk about the GIL.
3. Don’t even mention the GIL. No, seriously.
– David Beazley
Global Interpreter Lock (GIL)
I Only one thread runs in the interpreter at once
I Simplies many low-level details (memory management,callouts to C extensions, etc.)
I But then why did we see a speedup?I When a python thread does something IO related (reading or
writing a file, sending a network request, waiting for aresponse, etc.), it releases the lock
Recommended