<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.itcollege.ee/index.php?action=history&amp;feed=atom&amp;title=Advanced_Python_%28Fall_2017%29%2Flecture6</id>
	<title>Advanced Python (Fall 2017)/lecture6 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.itcollege.ee/index.php?action=history&amp;feed=atom&amp;title=Advanced_Python_%28Fall_2017%29%2Flecture6"/>
	<link rel="alternate" type="text/html" href="https://wiki.itcollege.ee/index.php?title=Advanced_Python_(Fall_2017)/lecture6&amp;action=history"/>
	<updated>2026-06-21T22:57:07Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://wiki.itcollege.ee/index.php?title=Advanced_Python_(Fall_2017)/lecture6&amp;diff=125100&amp;oldid=prev</id>
		<title>Eroman: Created page with &quot;= Lecture 6: Concurrency =  Concurrency is doing to things at once, not necessarily simultaneously.  == Task 1. ==  Make a socket echo server  === Solution ===  use google! th...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.itcollege.ee/index.php?title=Advanced_Python_(Fall_2017)/lecture6&amp;diff=125100&amp;oldid=prev"/>
		<updated>2017-10-23T22:08:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= Lecture 6: Concurrency =  Concurrency is doing to things at once, not necessarily simultaneously.  == Task 1. ==  Make a socket echo server  === Solution ===  use google! th...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Lecture 6: Concurrency =&lt;br /&gt;
&lt;br /&gt;
Concurrency is doing to things at once, not necessarily simultaneously.&lt;br /&gt;
&lt;br /&gt;
== Task 1. ==&lt;br /&gt;
&lt;br /&gt;
Make a socket echo server&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
use google! this one is from https://pymotw.com/3/socket/tcp.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;# socket_echo_server.py&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Create a TCP/IP socket&lt;br /&gt;
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;
&lt;br /&gt;
# Bind the socket to the port&lt;br /&gt;
server_address = (&amp;#039;localhost&amp;#039;, 10000)&lt;br /&gt;
print(&amp;#039;starting up on {} port {}&amp;#039;.format(*server_address))&lt;br /&gt;
sock.bind(server_address)&lt;br /&gt;
&lt;br /&gt;
# Listen for incoming connections&lt;br /&gt;
sock.listen(1)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
    # Wait for a connection&lt;br /&gt;
    print(&amp;#039;waiting for a connection&amp;#039;)&lt;br /&gt;
    connection, client_address = sock.accept()&lt;br /&gt;
    try:&lt;br /&gt;
        print(&amp;#039;connection from&amp;#039;, client_address)&lt;br /&gt;
&lt;br /&gt;
        # Receive the data in small chunks and retransmit it&lt;br /&gt;
        while True:&lt;br /&gt;
            data = connection.recv(16)&lt;br /&gt;
            print(&amp;#039;received {!r}&amp;#039;.format(data))&lt;br /&gt;
            if data:&lt;br /&gt;
                print(&amp;#039;sending data back to the client&amp;#039;)&lt;br /&gt;
                connection.sendall(data)&lt;br /&gt;
            else:&lt;br /&gt;
                print(&amp;#039;no data from&amp;#039;, client_address)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
    finally:&lt;br /&gt;
        # Clean up the connection&lt;br /&gt;
        connection.close()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
You can connect with this echo server with the command &amp;lt;code&amp;gt;nc localhost 10000&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Need for concurrency ==&lt;br /&gt;
&lt;br /&gt;
What happens if you try to open multiple connections to this socket server, and write a message?&lt;br /&gt;
&lt;br /&gt;
Does it respond with an echo?&lt;br /&gt;
&lt;br /&gt;
== Async ==&lt;br /&gt;
&lt;br /&gt;
python 3.4 adds a new library called asyncio which adds the ability to do ansychronous programming with python, using only the standard library. Asynchronous python, like javascript, has the ability to do something else when it is waiting.&lt;br /&gt;
&lt;br /&gt;
function with &amp;lt;code&amp;gt;async def&amp;lt;/code&amp;gt; are coroutines. actions which the async coroutine waits for are preceded with &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt; and are generators.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Here is an example of doing things out of order, and sleeping without blocking: https://asyncio.readthedocs.io/en/latest/hello_clock.html&lt;br /&gt;
&lt;br /&gt;
Here is a tcp echo server: https://asyncio.readthedocs.io/en/latest/tcp_echo.html&lt;br /&gt;
&lt;br /&gt;
here is an example that will stay connected until the connection is closed by the client&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;import asyncio&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async def handle_echo(reader, writer):&lt;br /&gt;
    while True:&lt;br /&gt;
        data = await reader.read(100)&lt;br /&gt;
        message = data.decode()&lt;br /&gt;
        addr = writer.get_extra_info(&amp;#039;peername&amp;#039;)&lt;br /&gt;
        print(&amp;quot;Received %r from %r&amp;quot; % (message, addr))&lt;br /&gt;
        if len(message.strip()) == 0:&lt;br /&gt;
            print(&amp;quot;Close the client socket&amp;quot;)&lt;br /&gt;
            writer.close()&lt;br /&gt;
            break&lt;br /&gt;
        print(&amp;quot;Send: %r&amp;quot; % message)&lt;br /&gt;
        writer.write(data)&lt;br /&gt;
        await writer.drain()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
loop = asyncio.get_event_loop()&lt;br /&gt;
coro = asyncio.start_server(handle_echo, &amp;#039;127.0.0.1&amp;#039;, 8888, loop=loop)&lt;br /&gt;
server = loop.run_until_complete(coro)&lt;br /&gt;
&lt;br /&gt;
# Serve requests until Ctrl+C is pressed&lt;br /&gt;
print(&amp;#039;Serving on {}&amp;#039;.format(server.sockets[0].getsockname()))&lt;br /&gt;
try:&lt;br /&gt;
    loop.run_forever()&lt;br /&gt;
except KeyboardInterrupt:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Close the server&lt;br /&gt;
server.close()&lt;br /&gt;
loop.run_until_complete(server.wait_closed())&lt;br /&gt;
loop.close()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
What happens if you make multiple connections with this server?&lt;br /&gt;
&lt;br /&gt;
== Threads ==&lt;br /&gt;
&lt;br /&gt;
Threads can run concurrently, and they share the same memory.&lt;br /&gt;
&lt;br /&gt;
this will take about 1 second to run using threads. without threads it would take 100 seconds&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;import threading&lt;br /&gt;
import time&lt;br /&gt;
threads = []&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def foo():&lt;br /&gt;
    time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in range(100):&lt;br /&gt;
    t = threading.Thread(target=foo)&lt;br /&gt;
    threads.append(t)&lt;br /&gt;
&lt;br /&gt;
for t in threads:&lt;br /&gt;
    t.start()&lt;br /&gt;
&lt;br /&gt;
for t in threads:&lt;br /&gt;
    t.join()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
&lt;br /&gt;
If you run this code with python 2, you will get different results each time you run it. It is not thread safe.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;import threading&lt;br /&gt;
threads = []&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
n = 0&lt;br /&gt;
&lt;br /&gt;
def foo():&lt;br /&gt;
    global n&lt;br /&gt;
    n += 1&lt;br /&gt;
&lt;br /&gt;
for i in range(1000):&lt;br /&gt;
    t = threading.Thread(target=foo)&lt;br /&gt;
    threads.append(t)&lt;br /&gt;
&lt;br /&gt;
for t in threads:&lt;br /&gt;
    t.start()&lt;br /&gt;
&lt;br /&gt;
for t in threads:&lt;br /&gt;
    t.join()&lt;br /&gt;
&lt;br /&gt;
print(n)&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Eroman</name></author>
	</entry>
</feed>