I/O

1. Input from the code


In [ ]:
a = input('Please, enter something: ')
print('You entered:', a)

2. Input from the OS prompt


In [ ]:
!cat argparse_example.py

In [ ]:
!python argparse_example.py -h

In [ ]:
!python argparse_example.py -i abc

Another posibility is to use Fire:


In [ ]:
%%writefile using_fire.py
import fire

class A():
    def do_something(self, x, y):
        print('Doing something with:', y, x)
        
fire.Fire(A)

In [ ]:
!python using_fire.py

In [ ]:
!python using_fire.py do-something hola caracola

3. Disk


In [ ]:
import io

Write some integers:


In [ ]:
# The legacy way:
file = open('/tmp/some_integers_1.txt', 'w')
file.write('{}\n'.format(1))
file.write('{}\n'.format(2))
file.write('{}\n'.format(3))
file.close()

In [ ]:
!cat /tmp/some_integers_1.txt

In [ ]:
# The modern (pythonic) alternative:
with io.open('/tmp/some_integers_2.txt', 'w') as file:
    file.write('{}\n'.format(1))
    file.write('{}\n'.format(2))
    file.write('{}\n'.format(3))

In [ ]:
file.closed

In [ ]:
!cat /tmp/some_integers_2.txt

Reading the file:


In [ ]:
# The classic alternative:
file = io.open('/tmp/some_integers_1.txt', 'r')
while True:
    line = file.readline()
    if not line:
        break
#for i in range(3):
    print(int(line))
file.close()

In [ ]:
# The pythonic alternarive:
with io.open('/tmp/some_integers_2.txt', 'r') as file:
    for line in file:
        print(int(line))

In [ ]:
file.closed

Opening modes

  1. r: Opens file for reading.
  2. w: Creates file for writting. Overwrites if exists.
  3. a: Opens file for appending (pointer at the end). Creates if does not exist.
  4. r+: Opens file for reading and writting. Does not overwrite. Does not create.
  5. w+: Opens file for reading and writting. Overwrites. Creates if does not exist.
  6. a+: Opens file for appending (pointer at the end) and reading. Creates if does not exist.

Binary VS Text modes

In the previous examples we have used the text mode for handling files, which basicaly means that we have using strings which can be edited with a text editor. On the other hand, binary files can not edited with a text editor, but are shorter than text files when storing numbers. The following code is the alternative to the previous one using binary mode.


In [ ]:
import struct # See https://docs.python.org/3/library/struct.html#format-characters

In [ ]:
with io.open('/tmp/some_integers_2.bin', 'wb') as file:
    file.write(struct.pack('h', 1)) # 2 bytes, signed int
    file.write(struct.pack('h', 2)) # 2 bytes, signed int
    file.write(struct.pack('i', 3)) # 4 bytes, signed int

In [ ]:
with io.open('/tmp/some_integers_2.bin', 'rb') as file:
    print(struct.unpack('h', file.read(struct.calcsize('h')))[0])
    print(struct.unpack('h', file.read(struct.calcsize('h')))[0])
    print(struct.unpack('i', file.read(struct.calcsize('i')))[0])

Persistence of objects (serialization) ... in disk


In [ ]:
import pickle
list = ['red', 'green', 'blue']
pickle.dump(list, open('list.dat','wb'))

In [ ]:
list2 = pickle.load(open('list.dat', 'rb'))
list2

4. Network

Using TCP:


In [ ]:
# This code creates a TCP receiver daemon

import socket

PORT = 8001

class TCP_Receiver():

    # We use a context manager for implementing this "server"
    # (https://docs.python.org/3/reference/datamodel.html#context-managers).
    # This method is run when the "with" context is created (see below).
    def __enter__(self):
        '''Create a TCP socket.'''
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.bind(('', PORT))
        self.sock.listen(1)
        print('waiting for a connection at {} ...'\
              .format(self.sock.getsockname()))
        return self

    def accept(self):
        (self.peer_sock, peer) = self.sock.accept()
        print('\nconnection accepted from {}'.format(peer))

    def receive(self):
        message_final_length = len('hello world!')
        message = bytearray()   # bytearray is mutable and therefore,
                                # faster appending than inmutable types
        while len(message) < message_final_length:
            chunk = self.peer_sock.recv(message_final_length - len(message))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            message.extend(chunk)
        #print('receivedddd "{}"'.format(message.decode("utf-8")))
        return message
    
    # This method is run when the "with" context is finised (see below).
    def __exit__(self,ext_type,exc_value,traceback):
        self.sock.close()
        print('socket closed')

def receiver_server():
    with TCP_Receiver() as recv:
        recv.accept()
        print('message = {}'.format(recv.receive().decode("utf-8")))
        
import threading

threading.Thread(target=receiver_server).start()

In [ ]:
# Now, we connect to the server.

# 1. Create a TCP socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', PORT))
print('connection established with {}'.format((sock.getpeername())))

# 2. Send a string to the server.
message = b'hello world!'
total_sent = 0 # bytes
while total_sent < len(message):
    sent = sock.send(message[total_sent:])
    if sent == 0:
        raise RuntimeError("socket connection broken")
    total_sent += sent
sock.close()

Using UDP:


In [ ]:
import socket

PORT = 8001

class UDP_Receiver():

    # We use a context manager (https://docs.python.org/3/reference/datamodel.html#context-managers).
    def __enter__(self):
        '''Create an UDP socket.'''
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('', PORT))
        print('listening at {} ...'\
              .format(self.sock.getsockname()))
        return self

    def receive(self):
        (message, from_addr) = self.sock.recvfrom(1024)
        print('received {} from {}'.format(message, from_addr))
        return message
    
    def __exit__(self,ext_type,exc_value,traceback):
        self.sock.close()
        print('socket closed')

def use_socket():
    with UDP_Receiver() as recv:
        print('message = {}'.format(recv.receive().decode("utf-8")))
        
import threading

threading.Thread(target=use_socket).start()

In [ ]:
# Create a UDP socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
message = b'hello world!'
sock.sendto(message, ('localhost', PORT))
sock.close()