Upgrade to Pro — share decks privately, control downloads, hide ads and more …

aiohttp_react.pdf

Yura Hulpa
August 05, 2016
65

 aiohttp_react.pdf

Yura Hulpa

August 05, 2016
Tweet

Transcript

  1. Introduction As a some of you might know, C Python

    has a Global Interpreter Lock (GIL) • It limits thread performance • It can be unpredictable 1 >>> import that 2 The Unwritten Rules of Python 3 1. You do not talk about the GIL. 4 2. You do NOT talk about the GIL. 5 3. Don't even mention the GIL. No seriously.
  2. Clever solution def countdown(n): """ very clever function """ while

    n > 0: n -= 1 if __name__ == '__main__': import time start_time = time.time() COUNT = 200000000 # 200 million countdown(COUNT) print("--- %s seconds ---" % (time.time() - start_time))
  3. Going into Threads… def countdown(n): """ very clever function """

    while n > 0: n -= 1 if __name__ == '__main__': import time from threading import Thread start_time = time.time() COUNT = 200000000 # 200 million # create a fancy two threads t1 = Thread(target=countdown,args=(COUNT//2,)) t2 = Thread(target=countdown,args=(COUNT//2,)) # start fancy threads t1.start(); t2.start() # join t1.join(); t2.join() print("--- %s seconds ---" % (time.time() - start_time))
  4. Result on dual core mac book Pro Sequential 8.58960700035 seconds

    2 threads on 2 cores 11.9105548859 seconds 2x slower 4 threads 19.9867351055 seconds WAT
  5. GIL Parallel execution is forbidden • There is a "global

    interpreter lock" • The GIL ensures that only one thread runs in the interpreter at once • Simplifies many low-level details (memory management, shot yourself into leg etc.)
  6. CPU Bound •CPU-bound threads that never perform I/O are handled

    as a special case • A "check" occurs every 100 “ticks” •Ticks are not related to time(Nice)
  7. Conclusion about threads: •Code became very hard to read •Hard

    to debug •Python is not able to use all advantages of POSIX threads …a lot of WAT moments
  8. Asyncio •Write code and pretend that it is sync :)

    •Fast growing community •Build in library of language •Clear syntax •Python 3.5
  9. Where to use fetching urls let’s use familiar to all

    Requests import requests import time URL = 'http://www.lp.edu.ua/' # NULP site :)) def fetch(url): resp = requests.get(url=url) return resp.text def fetch_all(urls): return [fetch(url) for url in urls] if __name__ == '__main__': start_time = time.time() urls = [URL] * 1000 fetch_all(urls) print("--- %s seconds ---" % (time.time() - start_time)) # 100 urls - ~70 sec
  10. aioh p async def fetch(url): async with ClientSession() as session:

    async with session.get(url) as response: return await response.text() async def bound_fetch(sem, url): # getter function with semaphore async with sem: await fetch(url) async def run(loop, r): url = 'http://www.lp.edu.ua/' # still NULP tasks = [] # create instance of Semaphore sem = asyncio.Semaphore(1000) for i in range(r): # pass Semaphore to every GET request task = asyncio.ensure_future(bound_fetch(sem, url)) tasks.append(task) responses = asyncio.gather(*tasks) await responses if __name__ == '__main__': start_time = time.time() number = 1000 loop = asyncio.get_event_loop() future = asyncio.ensure_future(run(loop, number)) loop.run_until_complete(future) print("--- %s seconds ---" % (time.time() - start_time))
  11. ge ing song METADATA_FILE = 'status-json.xsl' async def get_current_song(host, port):

    if port: host = ':'.join([host, port]) host = '/'.join([host, METADATA_FILE]) response = await aiohttp.request('GET', host) body = await response.json() title = body['icestats']['source'].get('title') await asyncio.sleep(2) return title
  12. publish into Redis(pub) def main(host, port): # get loop loop

    = asyncio.get_event_loop() while True: # getting title from ice cast server title = \ loop.run_until_complete(get_current_song(host, port)) if title: # connect to redis redis = \ loop.run_until_complete( create_redis(('localhost', 6379)) ) # and put song title into redis loop.run_until_complete( redis.publish('CHANNEL', json.dumps(title))) loop.close() return False
  13. get initial request and push track to client async def

    push_current_track(request): if request.headers['Accept'] != 'text/event-stream': raise web.HTTPFound('/') response = web.StreamResponse(status=200, headers={ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }) response.prepare(request) redis = await create_redis(('localhost', 6379)) channel = (await redis.subscribe('CHANNEL'))[0] while await channel.wait_message(): message = await channel.get() response.start(request) response.write(b'event: track_update\r\n') response.write(b'data: ' + message + b'\r\n\r\n') return response
  14. React != Angular 2(or 1.x) • Angular - full MVC

    framework with black jack and so on • React - V layer • with Angular you have all for SPA apps • Angular 2 is more about TS • with React you have large ecosystem of libraries that give flexibility
  15. React is all about components var App = React.createClass({ render:

    function(){ return ( <div>Component</div> ) } });
  16. Add to page var App = React.createClass({ render: function(){ return

    ( <div>Component</div> ) } }); ReactDOM.render(<App />, document.getElementById('app'));
  17. Do you want routing? import {LoginForm} from "./login.jsx"; import {AdminComponent}

    from "./admin.jsx" var App = React.createClass({ render: function(){ return ( <ReactRouter.Router history={ReactRouter.browserHistory}> <ReactRouter.Route path="/" url='login' component={ LoginForm }> </ReactRouter.Route> <ReactRouter.Route path="/login" url='login' component={ LoginForm }> </ReactRouter.Route> <ReactRouter.Route path="/admin" component={ AdminComponent }> </ReactRouter.Route> </ReactRouter.Router> ) } }); ReactDOM.render(<App />, document.getElementById('app'));
  18. Compatible with ES 6 class App extends React.Component { render()

    { return <div>ES 6 class</div>; } } ReactDOM.render(<App />, ocument.getElementById('app'));
  19. Ok, for ES6 you need Babel JS • So far

    browsers does not support ES6 syntax out of the box • Here Babel JS will help us • It ‘trnspile’ your ES6->ES5
  20. But to use Babel you will need…Webpack Webpack is packing

    tool for JS to make ‘bundles’ from your js
  21. Before <!--before you did it like this --> <script type="text/javascript"

    src="main.js"></script> <script type="text/javascript" src="login.js"></script> <script type="text/javascript" src="auth.js"></script> <script type="text/javascript" src="users.js"></script> <script type="text/javascript" src="animate.js"></ script> <script type="text/javascript" src=“graphs.js"></ script> <script type="text/javascript" src=“pusheen"></script> <script type="text/javascript" src=“pony.js"></script> <script type="text/javascript" src=“mr_robot.js"></ script>
  22. back to streamer.What to do on client? // create new

    eventSource var eventSource = new EventSource(“/api/track_stream"); eventSource.addEventListener("track_update",function(event){ // if u use jQuery just get song from event and put into tag $('.current-song').text(event.data); }); eventSource.onerror = function(event){ // oops console.log(event); }