├── Chapter 01 ├── calc.asm └── hello.asm ├── Chapter 02 ├── 01_lexer.py ├── 02_parser.py ├── 03_interpreter.py ├── ex00.py ├── ex01.py ├── ex02.py └── ex03.py ├── Chapter 03 ├── ex01.sh ├── ex02.sh ├── ex03.sh ├── ex04.sh ├── ex05.sh ├── ex06.sh ├── ex07.sh └── ex08.sh ├── Chapter 04 ├── Dockerfile ├── app.py ├── docker-compose.yml └── requirements.txt ├── Chapter 05 ├── connect.py ├── create_table.py ├── delete.py ├── last_select.py ├── project │ ├── create_db.py │ ├── fill_data.py │ ├── salary.sql │ ├── select_first.py │ ├── select_second.py │ └── select_third.py ├── seed.py ├── select.py └── update.py ├── Chapter 06 ├── ex01.py ├── ex02.py ├── ex03.py ├── ex04.py └── ex05.py ├── Chapter 07 ├── ex01.py ├── ex02.py ├── ex03.py ├── ex04.py ├── ex05.py ├── ex06.py ├── ex07.py ├── ex08.py ├── ex09.py ├── ex10.py ├── ex11.py ├── ex12.py ├── ex13.py └── ex14.py ├── Chapter 08 ├── ex01.py ├── ex02.py ├── ex03.py ├── ex04.py ├── ex05.py ├── ex06.py ├── ex07.py ├── ex08.py ├── ex09.py ├── ex10.py └── ex11.py ├── Chapter 09 ├── ex01.py ├── ex02.py ├── ex03.py ├── ex04.py ├── ex05.py ├── ex06.py ├── ex07.py ├── ex08.py ├── ex09.py ├── ex10.py ├── ex11.py ├── ex12.py ├── ex13.py ├── ex14.py ├── ex15.py ├── ex16.py ├── ex17.py └── ex18.py ├── Chapter 10 ├── .gitkeep ├── map-reduce01.py ├── map-reduce02.py ├── map-reduce03.py ├── map-reduce04.py ├── map01.py ├── map02.py ├── map03.py ├── map04.py ├── reduce01.py ├── reduce02.py └── reduce03.py ├── Chapter 11 ├── HTTP_Server │ ├── contact.html │ ├── error.html │ ├── images │ │ └── gupalo.jpg │ ├── index.html │ ├── main.py │ └── style.css ├── request01.py ├── request02.py ├── request03.py └── simple_http_server.py ├── Chapter 12 ├── Socket_examples │ ├── client_TCP_socket.py │ ├── client_UDP_socket.py │ ├── client_chat_socket.py │ ├── server_TCP_socket.py │ ├── server_UDP_socket.py │ ├── server_chat_socket.py │ └── simple_socket_server.py └── WebSockets_examples │ ├── chat │ ├── index.html │ ├── main.css │ ├── main.js │ └── server.py │ ├── index.html │ ├── permanent_connection │ ├── consumer.py │ ├── producer.py │ └── server.py │ ├── server.py │ ├── simple_client.py │ └── simple_server.py └── readme.md /Chapter 01/calc.asm: -------------------------------------------------------------------------------- 1 | org 0x100 ; Вказуємо, що це програма .COM 2 | section .data 3 | a db 5 ; Визначаємо a = 5 4 | b db 3 ; Визначаємо b = 3 5 | c db 2 ; Визначаємо c = 2 6 | resultMsg db 'Result: $' ; Визначення рядка для виведення результату 7 | 8 | section .text 9 | _start: 10 | mov al, [a] ; Завантажуємо a в al 11 | add al, [b] ; Додаємо b до al 12 | sub al, [c] ; Віднімаємо c від al 13 | 14 | ; Перетворення результату в ASCII символ (для однозначних чисел) 15 | add al, 30h ; Перетворюємо число в ASCII символ 16 | 17 | ; Виведення результату 18 | mov ah, 09h ; Функція DOS для виведення рядка 19 | lea dx, resultMsg ; Встановлюємо DX на адресу resultMsg 20 | int 21h ; Виклик DOS-переривання 21 | 22 | ; Виведення числа 23 | mov dl, al ; Поміщаємо результат в dl для виводу 24 | mov ah, 02h ; Функція DOS для виводу символу 25 | int 21h ; Виклик DOS-переривання 26 | 27 | ; Завершення програми 28 | mov ax, 4c00h ; Функція DOS для завершення програми 29 | int 21h ; Виклик DOS-переривання -------------------------------------------------------------------------------- /Chapter 01/hello.asm: -------------------------------------------------------------------------------- 1 | org 0x100 ; Вказівка, що це програма .COM 2 | section .data 3 | message db 'Hello, World!', '$' ; Визначення рядка для виведення 4 | 5 | section .text 6 | _start: 7 | mov ah, 09h ; Функція DOS для виведення рядка 8 | mov dx, message ; Встановити DX на адресу рядка 9 | int 21h ; Виклик DOS-переривання 10 | 11 | mov ax, 4c00h ; Функція DOS для завершення програми 12 | int 21h ; Виклик DOS-переривання -------------------------------------------------------------------------------- /Chapter 02/01_lexer.py: -------------------------------------------------------------------------------- 1 | class LexicalError(Exception): 2 | pass 3 | 4 | 5 | class SyntaxError(Exception): 6 | pass 7 | 8 | 9 | class TokenType: 10 | INTEGER = "INTEGER" 11 | PLUS = "PLUS" 12 | MINUS = "MINUS" 13 | EOF = "EOF" # Означає кінець вхідного рядка 14 | 15 | 16 | class Token: 17 | def __init__(self, type, value): 18 | self.type = type 19 | self.value = value 20 | 21 | def __str__(self): 22 | return f"Token({self.type}, {repr(self.value)})" 23 | 24 | 25 | class Lexer: 26 | def __init__(self, text): 27 | self.text = text 28 | self.pos = 0 29 | self.current_char = self.text[self.pos] 30 | 31 | def advance(self): 32 | """Переміщуємо 'вказівник' на наступний символ вхідного рядка""" 33 | self.pos += 1 34 | if self.pos > len(self.text) - 1: 35 | self.current_char = None # Означає кінець введення 36 | else: 37 | self.current_char = self.text[self.pos] 38 | 39 | def skip_whitespace(self): 40 | """Пропускаємо пробільні символи.""" 41 | while self.current_char is not None and self.current_char.isspace(): 42 | self.advance() 43 | 44 | def integer(self): 45 | """Повертаємо ціле число, зібране з послідовності цифр.""" 46 | result = "" 47 | while self.current_char is not None and self.current_char.isdigit(): 48 | result += self.current_char 49 | self.advance() 50 | return int(result) 51 | 52 | def get_next_token(self): 53 | """Лексичний аналізатор, що розбиває вхідний рядок на токени.""" 54 | while self.current_char is not None: 55 | if self.current_char.isspace(): 56 | self.skip_whitespace() 57 | continue 58 | 59 | if self.current_char.isdigit(): 60 | return Token(TokenType.INTEGER, self.integer()) 61 | 62 | if self.current_char == "+": 63 | self.advance() 64 | return Token(TokenType.PLUS, "+") 65 | 66 | if self.current_char == "-": 67 | self.advance() 68 | return Token(TokenType.MINUS, "-") 69 | 70 | raise LexicalError("Помилка лексичного аналізу") 71 | 72 | return Token(TokenType.EOF, None) 73 | 74 | 75 | def main(): 76 | while True: 77 | try: 78 | text = input('Введіть вираз (або "exit" для виходу): ') 79 | if text.lower() == "exit": 80 | print("Вихід із програми.") 81 | break 82 | lexer = Lexer(text) 83 | token = lexer.get_next_token() 84 | while token.type != TokenType.EOF: 85 | print(token) 86 | token = lexer.get_next_token() 87 | except Exception as e: 88 | print(e) 89 | 90 | 91 | if __name__ == "__main__": 92 | main() 93 | -------------------------------------------------------------------------------- /Chapter 02/02_parser.py: -------------------------------------------------------------------------------- 1 | class LexicalError(Exception): 2 | pass 3 | 4 | 5 | class ParsingError(Exception): 6 | pass 7 | 8 | 9 | class TokenType: 10 | INTEGER = "INTEGER" 11 | PLUS = "PLUS" 12 | MINUS = "MINUS" 13 | EOF = "EOF" # Означає кінець вхідного рядка 14 | 15 | 16 | class Token: 17 | def __init__(self, type, value): 18 | self.type = type 19 | self.value = value 20 | 21 | def __str__(self): 22 | return f"Token({self.type}, {repr(self.value)})" 23 | 24 | 25 | class Lexer: 26 | def __init__(self, text): 27 | self.text = text 28 | self.pos = 0 29 | self.current_char = self.text[self.pos] 30 | 31 | def advance(self): 32 | """Переміщуємо 'вказівник' на наступний символ вхідного рядка""" 33 | self.pos += 1 34 | if self.pos > len(self.text) - 1: 35 | self.current_char = None # Означає кінець введення 36 | else: 37 | self.current_char = self.text[self.pos] 38 | 39 | def skip_whitespace(self): 40 | """Пропускаємо пробільні символи.""" 41 | while self.current_char is not None and self.current_char.isspace(): 42 | self.advance() 43 | 44 | def integer(self): 45 | """Повертаємо ціле число, зібране з послідовності цифр.""" 46 | result = "" 47 | while self.current_char is not None and self.current_char.isdigit(): 48 | result += self.current_char 49 | self.advance() 50 | return int(result) 51 | 52 | def get_next_token(self): 53 | """Лексичний аналізатор, що розбиває вхідний рядок на токени.""" 54 | while self.current_char is not None: 55 | if self.current_char.isspace(): 56 | self.skip_whitespace() 57 | continue 58 | 59 | if self.current_char.isdigit(): 60 | return Token(TokenType.INTEGER, self.integer()) 61 | 62 | if self.current_char == "+": 63 | self.advance() 64 | return Token(TokenType.PLUS, "+") 65 | 66 | if self.current_char == "-": 67 | self.advance() 68 | return Token(TokenType.MINUS, "-") 69 | 70 | raise LexicalError("Помилка лексичного аналізу") 71 | 72 | return Token(TokenType.EOF, None) 73 | 74 | 75 | class AST: 76 | pass 77 | 78 | 79 | class BinOp(AST): 80 | def __init__(self, left, op, right): 81 | self.left = left 82 | self.op = op 83 | self.right = right 84 | 85 | 86 | class Num(AST): 87 | def __init__(self, token): 88 | self.token = token 89 | self.value = token.value 90 | 91 | 92 | class Parser: 93 | def __init__(self, lexer): 94 | self.lexer = lexer 95 | self.current_token = self.lexer.get_next_token() 96 | 97 | def error(self): 98 | raise ParsingError("Помилка синтаксичного аналізу") 99 | 100 | def eat(self, token_type): 101 | """ 102 | Порівнюємо поточний токен з очікуваним токеном і, якщо вони збігаються, 103 | 'поглинаємо' його і переходимо до наступного токена. 104 | """ 105 | if self.current_token.type == token_type: 106 | self.current_token = self.lexer.get_next_token() 107 | else: 108 | self.error() 109 | 110 | def term(self): 111 | """Парсер для 'term' правил граматики. У нашому випадку - це цілі числа.""" 112 | token = self.current_token 113 | self.eat(TokenType.INTEGER) 114 | return Num(token) 115 | 116 | def expr(self): 117 | """Парсер для арифметичних виразів.""" 118 | node = self.term() 119 | 120 | while self.current_token.type in (TokenType.PLUS, TokenType.MINUS): 121 | token = self.current_token 122 | if token.type == TokenType.PLUS: 123 | self.eat(TokenType.PLUS) 124 | elif token.type == TokenType.MINUS: 125 | self.eat(TokenType.MINUS) 126 | 127 | node = BinOp(left=node, op=token, right=self.term()) 128 | 129 | return node 130 | 131 | 132 | def print_ast(node, level=0): 133 | indent = " " * level 134 | if isinstance(node, Num): 135 | print(f"{indent}Num({node.value})") 136 | elif isinstance(node, BinOp): 137 | print(f"{indent}BinOp:") 138 | print(f"{indent} left: ") 139 | print_ast(node.left, level + 2) 140 | print(f"{indent} op: {node.op.type}") 141 | print(f"{indent} right: ") 142 | print_ast(node.right, level + 2) 143 | else: 144 | print(f"{indent}Unknown node type: {type(node)}") 145 | 146 | 147 | def main(): 148 | while True: 149 | try: 150 | text = input('Введіть вираз (або "exit" для виходу): ') 151 | if text.lower() == "exit": 152 | print("Вихід із програми.") 153 | break 154 | lexer = Lexer(text) 155 | parser = Parser(lexer) 156 | tree = parser.expr() 157 | print_ast(tree) 158 | except Exception as e: 159 | print(e) 160 | 161 | 162 | if __name__ == "__main__": 163 | main() 164 | -------------------------------------------------------------------------------- /Chapter 02/03_interpreter.py: -------------------------------------------------------------------------------- 1 | class LexicalError(Exception): 2 | pass 3 | 4 | 5 | class ParsingError(Exception): 6 | pass 7 | 8 | 9 | class TokenType: 10 | INTEGER = "INTEGER" 11 | PLUS = "PLUS" 12 | MINUS = "MINUS" 13 | EOF = "EOF" # Означає кінець вхідного рядка 14 | 15 | 16 | class Token: 17 | def __init__(self, type, value): 18 | self.type = type 19 | self.value = value 20 | 21 | def __str__(self): 22 | return f"Token({self.type}, {repr(self.value)})" 23 | 24 | 25 | class Lexer: 26 | def __init__(self, text): 27 | self.text = text 28 | self.pos = 0 29 | self.current_char = self.text[self.pos] 30 | 31 | def advance(self): 32 | """Переміщуємо 'вказівник' на наступний символ вхідного рядка""" 33 | self.pos += 1 34 | if self.pos > len(self.text) - 1: 35 | self.current_char = None # Означає кінець введення 36 | else: 37 | self.current_char = self.text[self.pos] 38 | 39 | def skip_whitespace(self): 40 | """Пропускаємо пробільні символи.""" 41 | while self.current_char is not None and self.current_char.isspace(): 42 | self.advance() 43 | 44 | def integer(self): 45 | """Повертаємо ціле число, зібране з послідовності цифр.""" 46 | result = "" 47 | while self.current_char is not None and self.current_char.isdigit(): 48 | result += self.current_char 49 | self.advance() 50 | return int(result) 51 | 52 | def get_next_token(self): 53 | """Лексичний аналізатор, що розбиває вхідний рядок на токени.""" 54 | while self.current_char is not None: 55 | if self.current_char.isspace(): 56 | self.skip_whitespace() 57 | continue 58 | 59 | if self.current_char.isdigit(): 60 | return Token(TokenType.INTEGER, self.integer()) 61 | 62 | if self.current_char == "+": 63 | self.advance() 64 | return Token(TokenType.PLUS, "+") 65 | 66 | if self.current_char == "-": 67 | self.advance() 68 | return Token(TokenType.MINUS, "-") 69 | 70 | raise LexicalError("Помилка лексичного аналізу") 71 | 72 | return Token(TokenType.EOF, None) 73 | 74 | 75 | class AST: 76 | pass 77 | 78 | 79 | class BinOp(AST): 80 | def __init__(self, left, op, right): 81 | self.left = left 82 | self.op = op 83 | self.right = right 84 | 85 | 86 | class Num(AST): 87 | def __init__(self, token): 88 | self.token = token 89 | self.value = token.value 90 | 91 | 92 | class Parser: 93 | def __init__(self, lexer): 94 | self.lexer = lexer 95 | self.current_token = self.lexer.get_next_token() 96 | 97 | def error(self): 98 | raise ParsingError("Помилка синтаксичного аналізу") 99 | 100 | def eat(self, token_type): 101 | """ 102 | Порівнюємо поточний токен з очікуваним токеном і, якщо вони збігаються, 103 | 'поглинаємо' його і переходимо до наступного токена. 104 | """ 105 | if self.current_token.type == token_type: 106 | self.current_token = self.lexer.get_next_token() 107 | else: 108 | self.error() 109 | 110 | def term(self): 111 | """Парсер для 'term' правил граматики. У нашому випадку - це цілі числа.""" 112 | token = self.current_token 113 | self.eat(TokenType.INTEGER) 114 | return Num(token) 115 | 116 | def expr(self): 117 | """Парсер для арифметичних виразів.""" 118 | node = self.term() 119 | 120 | while self.current_token.type in (TokenType.PLUS, TokenType.MINUS): 121 | token = self.current_token 122 | if token.type == TokenType.PLUS: 123 | self.eat(TokenType.PLUS) 124 | elif token.type == TokenType.MINUS: 125 | self.eat(TokenType.MINUS) 126 | 127 | node = BinOp(left=node, op=token, right=self.term()) 128 | 129 | return node 130 | 131 | 132 | def print_ast(node, level=0): 133 | indent = " " * level 134 | if isinstance(node, Num): 135 | print(f"{indent}Num({node.value})") 136 | elif isinstance(node, BinOp): 137 | print(f"{indent}BinOp:") 138 | print(f"{indent} left: ") 139 | print_ast(node.left, level + 2) 140 | print(f"{indent} op: {node.op.type}") 141 | print(f"{indent} right: ") 142 | print_ast(node.right, level + 2) 143 | else: 144 | print(f"{indent}Unknown node type: {type(node)}") 145 | 146 | 147 | class Interpreter: 148 | def __init__(self, parser): 149 | self.parser = parser 150 | 151 | def visit_BinOp(self, node): 152 | if node.op.type == TokenType.PLUS: 153 | return self.visit(node.left) + self.visit(node.right) 154 | elif node.op.type == TokenType.MINUS: 155 | return self.visit(node.left) - self.visit(node.right) 156 | 157 | def visit_Num(self, node): 158 | return node.value 159 | 160 | def interpret(self): 161 | tree = self.parser.expr() 162 | return self.visit(tree) 163 | 164 | def visit(self, node): 165 | method_name = "visit_" + type(node).__name__ 166 | visitor = getattr(self, method_name, self.generic_visit) 167 | return visitor(node) 168 | 169 | def generic_visit(self, node): 170 | raise Exception(f"Немає методу visit_{type(node).__name__}") 171 | 172 | 173 | def main(): 174 | while True: 175 | try: 176 | text = input('Введіть вираз (або "exit" для виходу): ') 177 | if text.lower() == "exit": 178 | print("Вихід із програми.") 179 | break 180 | lexer = Lexer(text) 181 | parser = Parser(lexer) 182 | interpreter = Interpreter(parser) 183 | result = interpreter.interpret() 184 | print(result) 185 | except Exception as e: 186 | print(e) 187 | 188 | 189 | if __name__ == "__main__": 190 | main() 191 | -------------------------------------------------------------------------------- /Chapter 02/ex00.py: -------------------------------------------------------------------------------- 1 | import ast 2 | 3 | code = "print('Hello, world!')" 4 | parsed_ast = ast.parse(code) 5 | 6 | # Виводимо рядок, що представляє AST 7 | print(ast.dump(parsed_ast, annotate_fields=True)) -------------------------------------------------------------------------------- /Chapter 02/ex01.py: -------------------------------------------------------------------------------- 1 | import ast 2 | 3 | 4 | class SimpleInterpreter(ast.NodeVisitor): 5 | def __init__(self): 6 | self.result = 0 7 | 8 | def visit_BinOp(self, node): 9 | left = self.visit(node.left) 10 | right = self.visit(node.right) 11 | if isinstance(node.op, ast.Add): 12 | return left + right 13 | elif isinstance(node.op, ast.Sub): 14 | return left - right 15 | else: 16 | raise ValueError(f"Unsupported operation: {type(node.op)}") 17 | 18 | def visit_Num(self, node): 19 | return node.n 20 | 21 | def interpret(self, code): 22 | tree = ast.parse(code) 23 | return self.visit(tree.body[0].value) 24 | 25 | 26 | if __name__ == '__main__': 27 | # Тестуємо інтерпретатор 28 | interpreter = SimpleInterpreter() 29 | print(interpreter.interpret("3 + 2")) # Виведе: 6 30 | -------------------------------------------------------------------------------- /Chapter 02/ex02.py: -------------------------------------------------------------------------------- 1 | import ast 2 | 3 | 4 | class ExtendedInterpreter(ast.NodeVisitor): 5 | def __init__(self): 6 | self.result = 0 7 | 8 | def visit_BinOp(self, node): 9 | left = self.visit(node.left) 10 | right = self.visit(node.right) 11 | if isinstance(node.op, ast.Add): 12 | return left + right 13 | elif isinstance(node.op, ast.Sub): 14 | return left - right 15 | elif isinstance(node.op, ast.Mult): 16 | return left * right 17 | elif isinstance(node.op, ast.Div): 18 | return left / right 19 | elif isinstance(node.op, ast.Pow): 20 | return left ** right 21 | else: 22 | raise ValueError(f"Unsupported operation: {type(node.op)}") 23 | 24 | def visit_Num(self, node): 25 | return node.n 26 | 27 | def visit_UnaryOp(self, node): 28 | operand = self.visit(node.operand) 29 | if isinstance(node.op, ast.USub): 30 | return -operand 31 | elif isinstance(node.op, ast.UAdd): 32 | return +operand 33 | else: 34 | raise ValueError(f"Unsupported unary operation: {type(node.op)}") 35 | 36 | def interpret(self, code): 37 | tree = ast.parse(code) 38 | return self.visit(tree.body[0].value) 39 | 40 | 41 | if __name__ == '__main__': 42 | 43 | # Тестування інтерпретатора 44 | interpreter = ExtendedInterpreter() 45 | print(interpreter.interpret("3 + 5 - 2")) # Виведе: 6 46 | print(interpreter.interpret("3 * 5")) # Виведе: 15 47 | print(interpreter.interpret("10 / 2")) # Виведе: 5.0 48 | print(interpreter.interpret("2 ** 3 + (1 - 3)")) # Виведе: 6 49 | print(interpreter.interpret("-3 + 5")) # Виведе: 2 50 | -------------------------------------------------------------------------------- /Chapter 02/ex03.py: -------------------------------------------------------------------------------- 1 | import ast 2 | 3 | 4 | class Interpreter(ast.NodeVisitor): 5 | def __init__(self): 6 | self.environment = {} 7 | 8 | def visit_Assign(self, node): 9 | value = self.visit(node.value) 10 | for target in node.targets: 11 | self.environment[target.id] = value 12 | 13 | def visit_BinOp(self, node): 14 | left = self.visit(node.left) 15 | right = self.visit(node.right) 16 | if isinstance(node.op, ast.Add): 17 | return left + right 18 | elif isinstance(node.op, ast.Sub): 19 | return left - right 20 | elif isinstance(node.op, ast.Mult): 21 | return left * right 22 | elif isinstance(node.op, ast.Div): 23 | return left / right 24 | 25 | def visit_Num(self, node): 26 | return node.n 27 | 28 | def visit_UnaryOp(self, node): 29 | operand = self.visit(node.operand) 30 | if isinstance(node.op, ast.USub): 31 | return -operand 32 | elif isinstance(node.op, ast.UAdd): 33 | return +operand 34 | else: 35 | raise ValueError(f"Unsupported unary operation: {type(node.op)}") 36 | 37 | def visit_Expr(self, node): 38 | return self.visit(node.value) 39 | 40 | def visit_For(self, node): 41 | # Assuming the loop iterates over a list of numbers 42 | iter_list = self.visit(node.iter) 43 | for item in iter_list: 44 | self.environment[node.target.id] = item 45 | for body_node in node.body: 46 | self.visit(body_node) 47 | 48 | def visit_Name(self, node): 49 | return self.environment.get(node.id, None) 50 | 51 | def visit_List(self, node): 52 | return [self.visit(e) for e in node.elts] 53 | 54 | def interpret(self, code): 55 | tree = ast.parse(code) 56 | self.visit(tree) 57 | 58 | 59 | if __name__ == '__main__': 60 | # Test the interpreter with a for loop 61 | interpreter = Interpreter() 62 | code = """ 63 | sum = 0 64 | my_list = [1, 2, 3] 65 | for i in my_list: 66 | sum = sum + i 67 | """ 68 | interpreter.interpret(code) 69 | print(interpreter.environment) 70 | 71 | -------------------------------------------------------------------------------- /Chapter 03/ex01.sh: -------------------------------------------------------------------------------- 1 | #оголошуємо змінну 2 | var="Hi!" 3 | #використовуємо змінну 4 | echo $var -------------------------------------------------------------------------------- /Chapter 03/ex02.sh: -------------------------------------------------------------------------------- 1 | #оголошуємо змінну num1 2 | num1=15 3 | #оголошуємо змінну num2 4 | num2=30 5 | #обчислюємо суму та зберігаємо її у змінній num3 6 | num3=$(($num1+$num2)) 7 | #виводимо на екран змінну sum 8 | echo "Сума: $num3" -------------------------------------------------------------------------------- /Chapter 03/ex03.sh: -------------------------------------------------------------------------------- 1 | #оголошуємо змінну 2 | var=7 3 | if [ $var -lt 10 ]; 4 | then 5 | echo "$var < 10" 6 | else 7 | echo "$var >= 10" 8 | fi -------------------------------------------------------------------------------- /Chapter 03/ex04.sh: -------------------------------------------------------------------------------- 1 | #оголошуємо змінну 2 | var=7 3 | #використовуємо оператор OR в if-умові 4 | if [[ ( $var -gt 5 ) || ( $var -eq 7 ) ]] 5 | then 6 | echo "$var >5 або =7" 7 | else 8 | echo "$var не >5 і не =7" 9 | fi -------------------------------------------------------------------------------- /Chapter 03/ex05.sh: -------------------------------------------------------------------------------- 1 | #оголошення змінної 2 | var=7 3 | #використовуємо оператор AND в if-умові 4 | if [[ ( $var -gt 5 ) && ( $var -lt 10 ) ]] 5 | then 6 | echo "виконані обидві умови" 7 | else 8 | echo "умови не виконані" 9 | fi -------------------------------------------------------------------------------- /Chapter 03/ex06.sh: -------------------------------------------------------------------------------- 1 | echo "Введіть число" 2 | read num 3 | if [ $num -gt 10 ]; 4 | then 5 | echo "Число > 10" 6 | elif [ $num -eq 10 ]; 7 | then 8 | echo "Число = 10" 9 | elif [ $num -lt 10 ]; 10 | then 11 | echo "Число < 10" 12 | else 13 | echo "Некоректне число" 14 | fi -------------------------------------------------------------------------------- /Chapter 03/ex07.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #оголошуємо цикл for 3 | for ((i=0; i<10; i++)) 4 | do 5 | #виводимо на екран значення змінної 6 | echo -n "$i " 7 | done 8 | echo "\n" -------------------------------------------------------------------------------- /Chapter 03/ex08.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #оголошуємо змінну 3 | var=1 4 | while [ $var -le 10 ] 5 | do 6 | echo "Значення змінної var =  $var" 7 | #збільшуємо значення змінної на 1 8 | (( var++ )) 9 | done -------------------------------------------------------------------------------- /Chapter 04/Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker-команда FROM вказує базовий образ контейнера 2 | # Наш базовий образ - це Linux з попередньо встановленим python-3.10 3 | FROM python:3.10 4 | 5 | # Встановимо змінну середовища 6 | ENV APP_HOME /app 7 | 8 | # Встановимо робочу директорію всередині контейнера 9 | WORKDIR $APP_HOME 10 | 11 | # Скопіюємо інші файли в робочу директорію контейнера 12 | COPY . . 13 | 14 | # Встановимо залежності всередині контейнера 15 | RUN pip install -r requirements.txt 16 | 17 | # Позначимо порт, де працює застосунок всередині контейнера 18 | EXPOSE 5000 19 | 20 | # Запустимо наш застосунок всередині контейнера 21 | ENTRYPOINT ["python", "app.py"] -------------------------------------------------------------------------------- /Chapter 04/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route("/") 7 | def hello(): 8 | return "Hello World!" 9 | 10 | 11 | if __name__ == "__main__": 12 | app.run(debug=False, host="0.0.0.0") 13 | -------------------------------------------------------------------------------- /Chapter 04/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | redis: 4 | image: redis:alpine 5 | ports: 6 | - '6379:6379' 7 | postgres: 8 | image: postgres:12 9 | environment: 10 | POSTGRES_DB: rest_app 11 | POSTGRES_USER: postgres 12 | POSTGRES_PASSWORD: 567234 13 | ports: 14 | - '5432:5432' 15 | volumes: 16 | - ./postgres-data:/var/lib/postgresql/data 17 | app: 18 | build: . 19 | ports: 20 | - '5000:5000' 21 | depends_on: 22 | - redis 23 | - postgres 24 | -------------------------------------------------------------------------------- /Chapter 04/requirements.txt: -------------------------------------------------------------------------------- 1 | click==8.1.3 2 | colorama==0.4.5 3 | Flask==2.2.2 4 | itsdangerous==2.1.2 5 | Jinja2==3.1.2 6 | MarkupSafe==2.1.1 7 | Werkzeug==2.2.2 8 | -------------------------------------------------------------------------------- /Chapter 05/connect.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | from contextlib import contextmanager 3 | 4 | database = "./test.db" 5 | 6 | 7 | @contextmanager 8 | def create_connection(db_file): 9 | """create a database connection to a SQLite database""" 10 | conn = sqlite3.connect(db_file) 11 | yield conn 12 | conn.rollback() 13 | conn.close() 14 | -------------------------------------------------------------------------------- /Chapter 05/create_table.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def create_table(conn, create_table_sql): 7 | """create a table from the create_table_sql statement 8 | :param conn: Connection object 9 | :param create_table_sql: a CREATE TABLE statement 10 | :return: 11 | """ 12 | try: 13 | c = conn.cursor() 14 | c.execute(create_table_sql) 15 | conn.commit() 16 | except Error as e: 17 | print(e) 18 | 19 | 20 | if __name__ == "__main__": 21 | sql_create_projects_table = """ 22 | CREATE TABLE IF NOT EXISTS projects ( 23 | id integer PRIMARY KEY, 24 | name text NOT NULL, 25 | begin_date text, 26 | end_date text 27 | ); 28 | """ 29 | 30 | sql_create_tasks_table = """ 31 | CREATE TABLE IF NOT EXISTS tasks ( 32 | id integer PRIMARY KEY, 33 | name text NOT NULL, 34 | priority integer, 35 | project_id integer NOT NULL, 36 | status Boolean default False, 37 | begin_date text NOT NULL, 38 | end_date text NOT NULL, 39 | FOREIGN KEY (project_id) REFERENCES projects (id) 40 | ); 41 | """ 42 | 43 | with create_connection(database) as conn: 44 | if conn is not None: 45 | # create projects table 46 | create_table(conn, sql_create_projects_table) 47 | # create tasks table 48 | create_table(conn, sql_create_tasks_table) 49 | else: 50 | print("Error! cannot create the database connection.") 51 | -------------------------------------------------------------------------------- /Chapter 05/delete.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def delete_task(conn, id): 7 | """ 8 | Delete a task by task id 9 | :param conn: Connection to the SQLite database 10 | :param id: id of the task 11 | :return: 12 | """ 13 | sql = "DELETE FROM tasks WHERE id=?" 14 | cur = conn.cursor() 15 | try: 16 | cur.execute(sql, (id,)) 17 | conn.commit() 18 | except Error as e: 19 | print(e) 20 | finally: 21 | cur.close() 22 | 23 | 24 | if __name__ == "__main__": 25 | with create_connection(database) as conn: 26 | delete_task(conn, 1) 27 | -------------------------------------------------------------------------------- /Chapter 05/last_select.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def select_projects(conn): 7 | """ 8 | Query all rows in the projects table with its tasks 9 | :param conn: the Connection object 10 | :return: rows projects or None 11 | """ 12 | rows = None 13 | cur = conn.cursor() 14 | try: 15 | cur.execute( 16 | "SELECT * FROM projects JOIN tasks ON tasks.project_id = projects.id;" 17 | ) 18 | rows = cur.fetchall() 19 | except Error as e: 20 | print(e) 21 | finally: 22 | cur.close() 23 | return rows 24 | 25 | 26 | if __name__ == "__main__": 27 | with create_connection(database) as conn: 28 | print("Projects:") 29 | projects = select_projects(conn) 30 | print(projects) 31 | -------------------------------------------------------------------------------- /Chapter 05/project/create_db.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | def create_db(): 5 | # читаємо файл зі скриптом для створення БД 6 | with open("salary.sql", "r") as f: 7 | sql = f.read() 8 | 9 | # створюємо з'єднання з БД (якщо файлу з БД немає, він буде створений) 10 | with sqlite3.connect("salary.db") as con: 11 | cur = con.cursor() 12 | # виконуємо скрипт із файлу, який створить таблиці в БД 13 | cur.executescript(sql) 14 | 15 | 16 | if __name__ == "__main__": 17 | create_db() 18 | -------------------------------------------------------------------------------- /Chapter 05/project/fill_data.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import faker 3 | from random import randint, choice 4 | import sqlite3 5 | 6 | NUMBER_COMPANIES = 3 7 | NUMBER_EMPLOYESS = 30 8 | NUMBER_POST = 5 9 | 10 | 11 | def generate_fake_data(number_companies, number_employees, number_post) -> tuple(): 12 | fake_companies = [] # тут зберігатимемо компанії 13 | fake_employees = [] # тут зберігатимемо співробітників 14 | fake_posts = [] # тут зберігатимемо посади 15 | """Візьмемо три компанії з faker і помістимо їх у потрібну змінну""" 16 | fake_data = faker.Faker() 17 | 18 | # Створимо набір компаній у кількості number_companies 19 | for _ in range(number_companies): 20 | fake_companies.append(fake_data.company()) 21 | 22 | # Згенеруємо тепер number_employees кількість співробітників''' 23 | for _ in range(number_employees): 24 | fake_employees.append(fake_data.name()) 25 | 26 | # Та number_post набір посад 27 | for _ in range(number_post): 28 | fake_posts.append(fake_data.job()) 29 | 30 | return fake_companies, fake_employees, fake_posts 31 | 32 | 33 | def prepare_data(companies, employees, posts) -> tuple(): 34 | for_companies = [] 35 | # готуємо список кортежів назв компаній 36 | for company in companies: 37 | for_companies.append((company,)) 38 | 39 | for_employees = [] # для таблиці employees 40 | 41 | for emp in employees: 42 | """ 43 | Для записів у таблицю співробітників нам потрібно додати посаду та id компанії. Компаній у нас було за замовчуванням 44 | NUMBER_COMPANIES, при створенні таблиці companies для поля id ми вказували INTEGER AUTOINCREMENT - тому кожен 45 | запис отримуватиме послідовне число збільшене на 1, починаючи з 1. Тому компанію вибираємо випадково 46 | у цьому діапазоні 47 | """ 48 | for_employees.append((emp, choice(posts), randint(1, NUMBER_COMPANIES))) 49 | 50 | """ 51 | Подібні операції виконаємо й у таблиці payments виплати зарплат. Приймемо, що виплата зарплати у всіх компаніях 52 | виконувалася з 10 по 20 числа кожного місяця. Діапазон зарплат генеруватимемо від 1000 до 10000 у.о. 53 | для кожного місяця та кожного співробітника. 54 | """ 55 | for_payments = [] 56 | 57 | for month in range(1, 12 + 1): 58 | # Виконуємо цикл за місяцями''' 59 | payment_date = datetime(2021, month, randint(10, 20)).date() 60 | for emp in range(1, NUMBER_EMPLOYESS + 1): 61 | # Виконуємо цикл за кількістю співробітників 62 | for_payments.append((emp, payment_date, randint(1000, 10000))) 63 | 64 | return for_companies, for_employees, for_payments 65 | 66 | 67 | def insert_data_to_db(companies, employees, payments) -> None: 68 | # Створимо з'єднання з нашою БД та отримаємо об'єкт курсора для маніпуляцій з даними 69 | 70 | with sqlite3.connect("salary.db") as con: 71 | cur = con.cursor() 72 | 73 | """Заповнюємо таблицю компаній. І створюємо скрипт для вставлення, де змінні, які вставлятимемо, помітимо 74 | знаком заповнювача (?) """ 75 | 76 | sql_to_companies = """INSERT INTO companies(company_name) 77 | VALUES (?)""" 78 | 79 | """Для вставлення відразу всіх даних скористаємося методом executemany курсора. Першим параметром буде текст 80 | скрипту, а другим - дані (список кортежів).""" 81 | 82 | cur.executemany(sql_to_companies, companies) 83 | 84 | # Далі вставляємо дані про співробітників. Напишемо для нього скрипт і вкажемо змінні 85 | 86 | sql_to_employees = """INSERT INTO employees(employee, post, company_id) 87 | VALUES (?, ?, ?)""" 88 | 89 | # Дані були підготовлені заздалегідь, тому просто передаємо їх у функцію 90 | 91 | cur.executemany(sql_to_employees, employees) 92 | 93 | # Останньою заповнюємо таблицю із зарплатами 94 | 95 | sql_to_payments = """INSERT INTO payments(employee_id, date_of, total) 96 | VALUES (?, ?, ?)""" 97 | 98 | # Вставляємо дані про зарплати 99 | 100 | cur.executemany(sql_to_payments, payments) 101 | 102 | # Фіксуємо наші зміни в БД 103 | 104 | con.commit() 105 | 106 | 107 | if __name__ == "__main__": 108 | companies, employees, posts = prepare_data( 109 | *generate_fake_data(NUMBER_COMPANIES, NUMBER_EMPLOYESS, NUMBER_POST) 110 | ) 111 | insert_data_to_db(companies, employees, posts) 112 | -------------------------------------------------------------------------------- /Chapter 05/project/salary.sql: -------------------------------------------------------------------------------- 1 | -- Table: companies 2 | DROP TABLE IF EXISTS companies; 3 | 4 | CREATE TABLE companies ( 5 | id INTEGER PRIMARY KEY AUTOINCREMENT, company_name VARCHAR(255) UNIQUE NOT NULL 6 | ); 7 | 8 | -- Table: employees 9 | DROP TABLE IF EXISTS employees; 10 | 11 | CREATE TABLE employees ( 12 | id INTEGER PRIMARY KEY AUTOINCREMENT, employee VARCHAR(255) UNIQUE NOT NULL, post VARCHAR(120) NOT NULL, company_id INTEGER, FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE ON UPDATE CASCADE 13 | ); 14 | 15 | -- Table: payments 16 | DROP TABLE IF EXISTS payments; 17 | 18 | CREATE TABLE payments ( 19 | id INTEGER PRIMARY KEY AUTOINCREMENT, employee_id INTEGER, date_of DATE NOT NULL, total INTEGER NOT NULL, FOREIGN KEY (employee_id) REFERENCES employees (id) ON DELETE CASCADE ON UPDATE CASCADE 20 | ); -------------------------------------------------------------------------------- /Chapter 05/project/select_first.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | def execute_query(sql: str) -> list: 5 | with sqlite3.connect("salary.db") as con: 6 | cur = con.cursor() 7 | cur.execute(sql) 8 | return cur.fetchall() 9 | 10 | 11 | sql = """ 12 | SELECT ROUND(AVG(p.total), 2), e.post 13 | FROM payments as p 14 | LEFT JOIN employees as e ON p.employee_id = e.id 15 | GROUP BY e.post; 16 | """ 17 | 18 | print(execute_query(sql)) 19 | -------------------------------------------------------------------------------- /Chapter 05/project/select_second.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | def execute_query(sql: str) -> list: 5 | with sqlite3.connect("salary.db") as con: 6 | cur = con.cursor() 7 | cur.execute(sql) 8 | return cur.fetchall() 9 | 10 | 11 | sql = """ 12 | SELECT COUNT(*), c.company_name 13 | FROM employees e 14 | LEFT JOIN companies c ON e.company_id = c.id 15 | GROUP BY c.id; 16 | """ 17 | 18 | print(execute_query(sql)) 19 | -------------------------------------------------------------------------------- /Chapter 05/project/select_third.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | def execute_query(sql: str) -> list: 5 | with sqlite3.connect("salary.db") as con: 6 | cur = con.cursor() 7 | cur.execute(sql) 8 | return cur.fetchall() 9 | 10 | 11 | sql = """ 12 | SELECT c.company_name, e.employee, e.post, p.total 13 | FROM companies c 14 | LEFT JOIN employees e ON e.company_id = c.id 15 | LEFT JOIN payments p ON p.employee_id = e.id 16 | WHERE p.total > 5000 17 | AND p.date_of BETWEEN '2021-07-10' AND '2021-07-20' 18 | """ 19 | 20 | print(execute_query(sql)) 21 | -------------------------------------------------------------------------------- /Chapter 05/seed.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def create_project(conn, project): 7 | """ 8 | Create a new project into the projects table 9 | :param conn: 10 | :param project: 11 | :return: project id 12 | """ 13 | sql = """ 14 | INSERT INTO projects(name,begin_date,end_date) VALUES(?,?,?); 15 | """ 16 | cur = conn.cursor() 17 | try: 18 | cur.execute(sql, project) 19 | conn.commit() 20 | except Error as e: 21 | print(e) 22 | finally: 23 | cur.close() 24 | 25 | return cur.lastrowid 26 | 27 | 28 | def create_task(conn, task): 29 | """ 30 | Create a new task 31 | :param conn: 32 | :param task: 33 | :return: 34 | """ 35 | 36 | sql = """ 37 | INSERT INTO tasks(name,priority,status,project_id,begin_date,end_date) VALUES(?,?,?,?,?,?); 38 | """ 39 | cur = conn.cursor() 40 | try: 41 | cur.execute(sql, task) 42 | conn.commit() 43 | except Error as e: 44 | print(e) 45 | finally: 46 | cur.close() 47 | 48 | return cur.lastrowid 49 | 50 | 51 | if __name__ == "__main__": 52 | with create_connection(database) as conn: 53 | # create a new project 54 | project = ("Cool App with SQLite & Python", "2022-01-01", "2022-01-30") 55 | project_id = create_project(conn, project) 56 | print(project_id) 57 | 58 | # tasks 59 | task_1 = ( 60 | "Analyze the requirements of the app", 61 | 1, 62 | True, 63 | project_id, 64 | "2022-01-01", 65 | "2022-01-02", 66 | ) 67 | task_2 = ( 68 | "Confirm with user about the top requirements", 69 | 1, 70 | False, 71 | project_id, 72 | "2022-01-03", 73 | "2022-01-05", 74 | ) 75 | 76 | # create tasks 77 | print(create_task(conn, task_1)) 78 | print(create_task(conn, task_2)) 79 | -------------------------------------------------------------------------------- /Chapter 05/select.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def select_projects(conn): 7 | """ 8 | Query all rows in the tasks table 9 | :param conn: the Connection object 10 | :return: rows projects 11 | """ 12 | rows = None 13 | cur = conn.cursor() 14 | try: 15 | cur.execute("SELECT * FROM projects;") 16 | rows = cur.fetchall() 17 | except Error as e: 18 | print(e) 19 | finally: 20 | cur.close() 21 | return rows 22 | 23 | 24 | def select_all_tasks(conn): 25 | """ 26 | Query all rows in the tasks table 27 | :param conn: the Connection object 28 | :return: rows tasks 29 | """ 30 | rows = None 31 | cur = conn.cursor() 32 | try: 33 | cur.execute("SELECT * FROM tasks") 34 | rows = cur.fetchall() 35 | except Error as e: 36 | print(e) 37 | finally: 38 | cur.close() 39 | return rows 40 | 41 | 42 | def select_task_by_status(conn, status): 43 | """ 44 | Query tasks by priority 45 | :param conn: the Connection object 46 | :param status: 47 | :return: rows tasks 48 | """ 49 | rows = None 50 | cur = conn.cursor() 51 | try: 52 | cur.execute("SELECT * FROM tasks WHERE status=?", (status,)) 53 | rows = cur.fetchall() 54 | except Error as e: 55 | print(e) 56 | finally: 57 | cur.close() 58 | return rows 59 | 60 | 61 | if __name__ == "__main__": 62 | with create_connection(database) as conn: 63 | print("Projects:") 64 | projects = select_projects(conn) 65 | print(projects) 66 | print("\nQuery all tasks") 67 | tasks = select_all_tasks(conn) 68 | print(tasks) 69 | print("\nQuery task by status:") 70 | task_by_priority = select_task_by_status(conn, True) 71 | print(task_by_priority) 72 | -------------------------------------------------------------------------------- /Chapter 05/update.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | 3 | from connect import create_connection, database 4 | 5 | 6 | def update_task(conn, parameters): 7 | """ 8 | update priority, begin_date, and end date of a task 9 | :param conn: 10 | :param parameters: 11 | :return: 12 | """ 13 | sql = """ 14 | UPDATE tasks 15 | SET priority = ?, begin_date = ?, end_date = ? 16 | WHERE id = ? 17 | """ 18 | cur = conn.cursor() 19 | try: 20 | cur.execute(sql, parameters) 21 | conn.commit() 22 | except Error as e: 23 | print(e) 24 | finally: 25 | cur.close() 26 | 27 | 28 | def update_task_status(conn, parameters): 29 | """ 30 | update priority, begin_date, and end date of a task 31 | :param conn: 32 | :param parameters: 33 | :return: 34 | """ 35 | sql = """ 36 | UPDATE tasks 37 | SET status = ? 38 | WHERE id = ? 39 | """ 40 | 41 | cur = conn.cursor() 42 | try: 43 | cur.execute(sql, parameters) 44 | conn.commit() 45 | except Error as e: 46 | print(e) 47 | finally: 48 | cur.close() 49 | 50 | 51 | if __name__ == "__main__": 52 | with create_connection(database) as conn: 53 | update_task(conn, (2, "2022-01-04", "2022-01-06", 1)) 54 | update_task_status(conn, (True, 2)) 55 | -------------------------------------------------------------------------------- /Chapter 06/ex01.py: -------------------------------------------------------------------------------- 1 | from pymongo import MongoClient 2 | from pymongo.server_api import ServerApi 3 | 4 | client = MongoClient( 5 | "mongodb+srv://:@krabaton.5mlpr.gcp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", 6 | server_api=ServerApi("1"), 7 | ) 8 | 9 | db = client.book 10 | 11 | result_one = db.cats.insert_one( 12 | { 13 | "name": "barsik", 14 | "age": 3, 15 | "features": ["ходить в капці", "дає себе гладити", "рудий"], 16 | } 17 | ) 18 | 19 | print(result_one.inserted_id) 20 | 21 | result_many = db.cats.insert_many( 22 | [ 23 | { 24 | "name": "Lama", 25 | "age": 2, 26 | "features": ["ходить в лоток", "не дає себе гладити", "сірий"], 27 | }, 28 | { 29 | "name": "Liza", 30 | "age": 4, 31 | "features": ["ходить в лоток", "дає себе гладити", "білий"], 32 | }, 33 | ] 34 | ) 35 | print(result_many.inserted_ids) 36 | -------------------------------------------------------------------------------- /Chapter 06/ex02.py: -------------------------------------------------------------------------------- 1 | from bson.objectid import ObjectId 2 | 3 | from pymongo import MongoClient 4 | from pymongo.server_api import ServerApi 5 | 6 | client = MongoClient( 7 | "mongodb+srv://:@krabaton.5mlpr.gcp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", 8 | server_api=ServerApi("1"), 9 | ) 10 | 11 | db = client.book 12 | 13 | result = db.cats.find_one({"_id": ObjectId("60d24b783733b1ae668d4a77")}) 14 | print(result) 15 | -------------------------------------------------------------------------------- /Chapter 06/ex03.py: -------------------------------------------------------------------------------- 1 | from pymongo import MongoClient 2 | from pymongo.server_api import ServerApi 3 | 4 | client = MongoClient( 5 | "mongodb+srv://:@krabaton.5mlpr.gcp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", 6 | server_api=ServerApi("1"), 7 | ) 8 | db = client.book 9 | 10 | result = db.cats.find({}) 11 | for el in result: 12 | print(el) 13 | -------------------------------------------------------------------------------- /Chapter 06/ex04.py: -------------------------------------------------------------------------------- 1 | from bson.objectid import ObjectId 2 | 3 | from pymongo import MongoClient 4 | from pymongo.server_api import ServerApi 5 | 6 | client = MongoClient( 7 | "mongodb+srv://:@krabaton.5mlpr.gcp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", 8 | server_api=ServerApi("1"), 9 | ) 10 | db = client.book 11 | 12 | db.cats.update_one({"name": "barsik"}, {"$set": {"age": 4}}) 13 | result = db.cats.find_one({"name": "barsik"}) 14 | print(result) 15 | -------------------------------------------------------------------------------- /Chapter 06/ex05.py: -------------------------------------------------------------------------------- 1 | from bson.objectid import ObjectId 2 | 3 | from pymongo import MongoClient 4 | from pymongo.server_api import ServerApi 5 | 6 | client = MongoClient( 7 | "mongodb+srv://:@krabaton.5mlpr.gcp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", 8 | server_api=ServerApi("1"), 9 | ) 10 | db = client.book 11 | 12 | db.cats.delete_one({"name": "barsik"}) 13 | result = db.cats.find_one({"name": "barsik"}) 14 | print(result) 15 | -------------------------------------------------------------------------------- /Chapter 07/ex01.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | import logging 3 | from time import sleep 4 | 5 | 6 | class MyThread(Thread): 7 | def __init__( 8 | self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None 9 | ): 10 | super().__init__(group=group, target=target, name=name, daemon=daemon) 11 | self.args = args 12 | self.kwargs = kwargs 13 | 14 | def run(self) -> None: 15 | sleep(2) 16 | logging.debug("Wake up!") 17 | logging.debug(f"args: {self.args}") 18 | 19 | 20 | if __name__ == "__main__": 21 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 22 | for i in range(5): 23 | thread = MyThread(args=(f"Count thread - {i}",)) 24 | thread.start() 25 | print("Usefull message") 26 | -------------------------------------------------------------------------------- /Chapter 07/ex02.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | from time import sleep 3 | import logging 4 | 5 | 6 | class UsefulClass: 7 | def __init__(self, second_num): 8 | self.delay = second_num 9 | 10 | def __call__(self): 11 | sleep(self.delay) 12 | logging.debug("Wake up!") 13 | 14 | 15 | if __name__ == "__main__": 16 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 17 | t2 = UsefulClass(2) 18 | thread = Thread(target=t2) 19 | thread.start() 20 | print("Some stuff") 21 | -------------------------------------------------------------------------------- /Chapter 07/ex03.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | from time import sleep 3 | import logging 4 | 5 | 6 | def example_work(delay): 7 | sleep(delay) 8 | logging.debug("Wake up!") 9 | 10 | 11 | if __name__ == "__main__": 12 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 13 | for i in range(5): 14 | thread = Thread(target=example_work, args=(i,)) 15 | thread.start() 16 | -------------------------------------------------------------------------------- /Chapter 07/ex04.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def example_work(params): 7 | sleep(params) 8 | logging.debug("Wake up!") 9 | 10 | 11 | if __name__ == "__main__": 12 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 13 | logging.debug("Start program") 14 | threads = [] 15 | for i in range(5): 16 | thread = Thread(target=example_work, args=(i,)) 17 | thread.start() 18 | threads.append(thread) 19 | 20 | [el.join() for el in threads] 21 | 22 | logging.debug("End program") 23 | -------------------------------------------------------------------------------- /Chapter 07/ex05.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | from time import sleep 3 | import logging 4 | 5 | 6 | class UsefulClass: 7 | def __init__(self, second_num): 8 | self.delay = second_num 9 | 10 | def __call__(self): 11 | sleep(self.delay) 12 | logging.debug("Wake up!") 13 | 14 | 15 | if __name__ == "__main__": 16 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 17 | t2 = UsefulClass(2) 18 | thread = Thread(target=t2) 19 | thread_locking = Thread(target=t2) 20 | 21 | thread.start() 22 | print(thread.is_alive(), thread_locking.is_alive()) 23 | thread_locking.start() 24 | thread.join() 25 | thread_locking.join() 26 | print(thread.is_alive(), thread_locking.is_alive()) 27 | print("After all...") 28 | -------------------------------------------------------------------------------- /Chapter 07/ex06.py: -------------------------------------------------------------------------------- 1 | from threading import Timer 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def example_work(): 7 | logging.debug("Start!") 8 | 9 | 10 | if __name__ == "__main__": 11 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 12 | 13 | first = Timer(0.5, example_work) 14 | first.name = "First thread" 15 | second = Timer(0.7, example_work) 16 | second.name = "Second thread" 17 | logging.debug("Start timers") 18 | first.start() 19 | second.start() 20 | sleep(0.6) 21 | second.cancel() 22 | 23 | logging.debug("End program") 24 | -------------------------------------------------------------------------------- /Chapter 07/ex07.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, RLock 2 | import logging 3 | from time import time, sleep 4 | 5 | lock = RLock() 6 | 7 | 8 | def func(locker, delay): 9 | timer = time() 10 | locker.acquire() 11 | sleep(delay) 12 | locker.release() 13 | logging.debug(f"Done {time() - timer}") 14 | 15 | 16 | if __name__ == "__main__": 17 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 18 | t1 = Thread(target=func, args=(lock, 2)) 19 | t2 = Thread(target=func, args=(lock, 2)) 20 | t1.start() 21 | t2.start() 22 | logging.debug("Started") 23 | -------------------------------------------------------------------------------- /Chapter 07/ex08.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, RLock 2 | import logging 3 | from time import time, sleep 4 | 5 | lock = RLock() 6 | 7 | 8 | def func(locker, delay): 9 | timer = time() 10 | with locker: 11 | sleep(delay) 12 | logging.debug(f"Done {time() - timer}") 13 | 14 | 15 | if __name__ == "__main__": 16 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 17 | t1 = Thread(target=func, args=(lock, 2)) 18 | t2 = Thread(target=func, args=(lock, 2)) 19 | t1.start() 20 | t2.start() 21 | logging.debug("Started") 22 | -------------------------------------------------------------------------------- /Chapter 07/ex09.py: -------------------------------------------------------------------------------- 1 | from threading import Semaphore, Thread 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def worker(condition): 7 | with condition: 8 | logging.debug(f"Got semaphore") 9 | sleep(1) 10 | logging.debug(f"finished") 11 | 12 | 13 | if __name__ == "__main__": 14 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 15 | pool = Semaphore(2) 16 | for num in range(10): 17 | thread = Thread(name=f"Th-{num}", target=worker, args=(pool,)) 18 | thread.start() 19 | -------------------------------------------------------------------------------- /Chapter 07/ex10.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, Condition 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def worker(condition: Condition): 7 | logging.debug("Worker ready to work") 8 | with condition: 9 | condition.wait() 10 | logging.debug("The worker can do the work") 11 | 12 | 13 | def master(condition: Condition): 14 | logging.debug("Master doing some work") 15 | sleep(2) 16 | with condition: 17 | logging.debug("Informing that workers can do the work") 18 | condition.notify_all() 19 | 20 | 21 | if __name__ == "__main__": 22 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 23 | condition = Condition() 24 | master = Thread(name="master", target=master, args=(condition,)) 25 | 26 | worker_one = Thread(name="worker_one", target=worker, args=(condition,)) 27 | worker_two = Thread(name="worker_two", target=worker, args=(condition,)) 28 | worker_one.start() 29 | worker_two.start() 30 | master.start() 31 | 32 | logging.debug("End program") 33 | -------------------------------------------------------------------------------- /Chapter 07/ex11.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, Event 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def worker(event: Event): 7 | logging.debug("Worker ready to work") 8 | event.wait() 9 | logging.debug("The worker can do the work") 10 | 11 | 12 | def master(event: Event): 13 | logging.debug("Master doing some work") 14 | sleep(2) 15 | logging.debug("Informing that workers can do the work") 16 | event.set() 17 | 18 | 19 | if __name__ == "__main__": 20 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 21 | event = Event() 22 | master = Thread(name="master", target=master, args=(event,)) 23 | 24 | worker_one = Thread(name="worker_one", target=worker, args=(event,)) 25 | worker_two = Thread(name="worker_two", target=worker, args=(event,)) 26 | worker_one.start() 27 | worker_two.start() 28 | master.start() 29 | 30 | logging.debug("End program") 31 | -------------------------------------------------------------------------------- /Chapter 07/ex12.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, Event 2 | import logging 3 | from time import sleep 4 | 5 | 6 | def example_work(event_for_exit: Event): 7 | while True: 8 | sleep(1) 9 | logging.debug("Run event work") 10 | 11 | if event_for_exit.is_set(): 12 | break 13 | 14 | 15 | if __name__ == "__main__": 16 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 17 | event = Event() 18 | thread = Thread(target=example_work, args=(event,)) 19 | thread.start() 20 | 21 | sleep(5) 22 | event.set() 23 | 24 | logging.debug("End program") 25 | -------------------------------------------------------------------------------- /Chapter 07/ex13.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | from threading import Thread, Barrier 3 | import logging 4 | from time import sleep, ctime 5 | 6 | 7 | def worker(barrier: Barrier): 8 | logging.debug(f"Start thread: {ctime()}") 9 | sleep(randint(1, 3)) # Simulate some work 10 | r = barrier.wait() 11 | logging.debug(f"count: {r}") 12 | logging.debug(f"Barrier overcome: {ctime()}") 13 | 14 | 15 | if __name__ == "__main__": 16 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 17 | barrier = Barrier(5) 18 | 19 | for num in range(10): 20 | thread = Thread(name=f"Th-{num}", target=worker, args=(barrier,)) 21 | thread.start() 22 | -------------------------------------------------------------------------------- /Chapter 07/ex14.py: -------------------------------------------------------------------------------- 1 | import concurrent.futures 2 | import logging 3 | from random import randint 4 | from time import sleep 5 | 6 | 7 | def greeting(name): 8 | logging.debug(f"greeting for: {name}") 9 | sleep(randint(0, 3)) 10 | return f"Hello {name}" 11 | 12 | 13 | arguments = ( 14 | "Bill", 15 | "Jill", 16 | "Till", 17 | "Sam", 18 | "Tom", 19 | "John", 20 | ) 21 | 22 | if __name__ == "__main__": 23 | logging.basicConfig(level=logging.DEBUG, format="%(threadName)s %(message)s") 24 | with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: 25 | results = list(executor.map(greeting, arguments)) 26 | 27 | logging.debug(results) 28 | -------------------------------------------------------------------------------- /Chapter 08/ex01.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Process 2 | import logging 3 | from time import sleep 4 | 5 | logger = logging.getLogger() 6 | stream_handler = logging.StreamHandler() 7 | logger.addHandler(stream_handler) 8 | logger.setLevel(logging.DEBUG) 9 | 10 | 11 | class MyProcess(Process): 12 | def __init__( 13 | self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None 14 | ): 15 | super().__init__(group=group, target=target, name=name, daemon=daemon) 16 | self.args = args 17 | 18 | def run(self) -> None: 19 | logger.debug(self.args) 20 | 21 | 22 | def example_work(params): 23 | sleep(0.5) 24 | logger.debug(params) 25 | 26 | 27 | if __name__ == "__main__": 28 | processes = [] 29 | for i in range(3): 30 | pr = Process(target=example_work, args=(f"Count process function - {i}",)) 31 | pr.start() 32 | processes.append(pr) 33 | 34 | for i in range(2): 35 | pr = MyProcess(args=(f"Count process class - {i}",)) 36 | pr.start() 37 | processes.append(pr) 38 | 39 | [el.join() for el in processes] 40 | [print(el.exitcode, end=" ") for el in processes] 41 | logger.debug("End program") 42 | -------------------------------------------------------------------------------- /Chapter 08/ex02.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Process, Value, RLock, current_process 2 | from time import sleep 3 | import logging 4 | import sys 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | 12 | def worker(val: Value): 13 | logger.debug(f"Started {current_process().name}") 14 | sleep(1) 15 | with val.get_lock(): 16 | val.value += 1 17 | logger.debug(f"Done {current_process().name}") 18 | sys.exit(0) 19 | 20 | 21 | if __name__ == "__main__": 22 | lock = RLock() 23 | value = Value("d", 0, lock=lock) 24 | pr1 = Process(target=worker, args=(value,)) 25 | pr1.start() 26 | pr2 = Process(target=worker, args=(value,)) 27 | pr2.start() 28 | 29 | pr1.join() 30 | pr2.join() 31 | 32 | print(value.value) # 2.0 33 | -------------------------------------------------------------------------------- /Chapter 08/ex03.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Process, RLock, current_process 2 | from multiprocessing.sharedctypes import Value, Array 3 | from ctypes import Structure, c_double 4 | import logging 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | 12 | class Point(Structure): 13 | _fields_ = [("x", c_double), ("y", c_double)] 14 | 15 | 16 | def modify(num: Value, string: Array, arr: Array): 17 | logger.debug(f"Started {current_process().name}") 18 | logger.debug(f"Change num: {num.value}") 19 | with num.get_lock(): 20 | num.value **= 2 21 | logger.debug(f"to num: {num.value}") 22 | with string.get_lock(): 23 | string.value = string.value.upper() 24 | with arr.get_lock(): 25 | for a in arr: 26 | a.x **= 2 27 | a.y **= 2 28 | logger.debug(f"Done {current_process().name}") 29 | 30 | 31 | if __name__ == "__main__": 32 | lock = RLock() 33 | number = Value(c_double, 1.5, lock=lock) 34 | string = Array("c", b"hello world", lock=lock) 35 | array = Array(Point, [(1, -6), (-5, 2), (2, 9)], lock=lock) 36 | 37 | p = Process(target=modify, args=(number, string, array)) 38 | p2 = Process(target=modify, args=(number, string, array)) 39 | p.start() 40 | p2.start() 41 | p.join() 42 | p2.join() 43 | print(number.value) 44 | print(string.value) 45 | print([(arr.x, arr.y) for arr in array]) 46 | -------------------------------------------------------------------------------- /Chapter 08/ex04.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Process, Manager, current_process 2 | from random import randint 3 | from time import sleep 4 | import logging 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | 12 | def worker(delay, val: Manager): 13 | name = current_process().name 14 | logger.debug(f"Started: {name}") 15 | sleep(delay) 16 | val[name] = current_process().pid 17 | logger.debug(f"Done: {name}") 18 | 19 | 20 | if __name__ == "__main__": 21 | with Manager() as manager: 22 | m = manager.dict() 23 | processes = [] 24 | for i in range(5): 25 | pr = Process(target=worker, args=(randint(1, 3), m)) 26 | pr.start() 27 | processes.append(pr) 28 | 29 | [pr.join() for pr in processes] 30 | print(m) 31 | -------------------------------------------------------------------------------- /Chapter 08/ex05.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Manager, Process 2 | import time 3 | 4 | 5 | def modify_first(shared_list): 6 | shared_list[0]["key1"] = "modified by first process" 7 | print("First Process: Modified the first dictionary") 8 | 9 | 10 | def modify_third(shared_list): 11 | shared_list[2]["key3"] = "modified by third process" 12 | print("Third Process: Modified the third dictionary") 13 | 14 | 15 | def read(shared_list): 16 | # Чекаємо деякий час, щоб зміни були внесені 17 | time.sleep(2) 18 | readable_list = [dict(proxy_dict) for proxy_dict in shared_list] 19 | print(f"Read Process: Read the shared list - {readable_list}") 20 | 21 | 22 | if __name__ == "__main__": 23 | with Manager() as manager: 24 | shared_list = manager.list( 25 | [{"key1": "original1"}, {"key2": "original2"}, {"key3": "original3"}] 26 | ) 27 | p1 = Process(target=modify_first, args=(shared_list,)) 28 | p2 = Process(target=modify_third, args=(shared_list,)) 29 | p3 = Process(target=read, args=(shared_list,)) 30 | 31 | p1.start() 32 | p2.start() 33 | p3.start() 34 | 35 | p1.join() 36 | p2.join() 37 | p3.join() 38 | -------------------------------------------------------------------------------- /Chapter 08/ex06.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Manager, Process 2 | import time 3 | 4 | 5 | def modify_first(shared_list): 6 | shared_list[0]["key1"] = "modified by first process" 7 | print("First Process: Modified the first dictionary") 8 | 9 | 10 | def modify_third(shared_list): 11 | shared_list[2]["key3"] = "modified by third process" 12 | print("Third Process: Modified the third dictionary") 13 | 14 | 15 | def read(shared_list): 16 | # Чекаємо деякий час, щоб зміни були внесені 17 | time.sleep(2) 18 | readable_list = [dict(proxy_dict) for proxy_dict in shared_list] 19 | print(f"Read Process: Read the shared list - {readable_list}") 20 | 21 | 22 | if __name__ == "__main__": 23 | with Manager() as manager: 24 | shared_list = manager.list( 25 | [ 26 | manager.dict({"key1": "original1"}), 27 | manager.dict({"key2": "original2"}), 28 | manager.dict({"key3": "original3"}), 29 | ] 30 | ) 31 | p1 = Process(target=modify_first, args=(shared_list,)) 32 | p2 = Process(target=modify_third, args=(shared_list,)) 33 | p3 = Process(target=read, args=(shared_list,)) 34 | 35 | p1.start() 36 | p2.start() 37 | p3.start() 38 | 39 | p1.join() 40 | p2.join() 41 | p3.join() 42 | -------------------------------------------------------------------------------- /Chapter 08/ex07.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Pipe, Process, current_process 2 | from time import sleep 3 | import sys 4 | import logging 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | recipient1, sender1 = Pipe() 12 | recipient2, sender2 = Pipe() 13 | 14 | 15 | def worker(pipe: Pipe): 16 | name = current_process().name 17 | logger.debug(f"{name} started...") 18 | val = pipe.recv() 19 | logger.debug(val**2) 20 | sys.exit(0) 21 | 22 | 23 | if __name__ == "__main__": 24 | w1 = Process(target=worker, args=(recipient1,)) 25 | w2 = Process(target=worker, args=(recipient2,)) 26 | 27 | w1.start() 28 | w2.start() 29 | 30 | sender1.send(8) 31 | sleep(1) 32 | sender2.send(16) 33 | -------------------------------------------------------------------------------- /Chapter 08/ex08.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Queue, Process, current_process 2 | from time import sleep 3 | import sys 4 | import logging 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | q = Queue() 12 | 13 | 14 | def worker(queue: Queue): 15 | name = current_process().name 16 | logger.debug(f"{name} started...") 17 | val = queue.get() 18 | logger.debug(f"{name} {val**2}") 19 | sys.exit(0) 20 | 21 | 22 | if __name__ == "__main__": 23 | w1 = Process(target=worker, args=(q,)) 24 | w2 = Process(target=worker, args=(q,)) 25 | 26 | w1.start() 27 | w2.start() 28 | 29 | q.put(8) 30 | sleep(1) 31 | q.put(16) 32 | -------------------------------------------------------------------------------- /Chapter 08/ex09.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import JoinableQueue, Process, current_process 2 | from time import sleep 3 | import sys 4 | import logging 5 | 6 | logger = logging.getLogger() 7 | stream_handler = logging.StreamHandler() 8 | logger.addHandler(stream_handler) 9 | logger.setLevel(logging.DEBUG) 10 | 11 | jq = JoinableQueue() 12 | 13 | 14 | def worker(jqueue: JoinableQueue): 15 | name = current_process().name 16 | logger.debug(f"{name} started...") 17 | val = jqueue.get() 18 | logger.debug(f"{name} {val**2}") 19 | sleep(1) 20 | jqueue.task_done() 21 | sys.exit(0) 22 | 23 | 24 | if __name__ == "__main__": 25 | w1 = Process(target=worker, args=(jq,)) 26 | w2 = Process(target=worker, args=(jq,)) 27 | 28 | w1.start() 29 | w2.start() 30 | 31 | jq.put(8) 32 | sleep(1) 33 | jq.put(16) 34 | jq.join() 35 | print("Finished") 36 | -------------------------------------------------------------------------------- /Chapter 08/ex10.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Pool, current_process 2 | import logging 3 | 4 | logger = logging.getLogger() 5 | stream_handler = logging.StreamHandler() 6 | logger.addHandler(stream_handler) 7 | logger.setLevel(logging.DEBUG) 8 | 9 | 10 | def worker(x): 11 | logger.debug(f"pid={current_process().pid}, x={x}") 12 | return x * x 13 | 14 | 15 | if __name__ == "__main__": 16 | with Pool(processes=2) as pool: 17 | logger.debug(pool.map(worker, range(10))) 18 | -------------------------------------------------------------------------------- /Chapter 08/ex11.py: -------------------------------------------------------------------------------- 1 | import concurrent.futures 2 | import math 3 | 4 | 5 | PRIMES = [ 6 | 112272535095293, 7 | 112582705942171, 8 | 112272535095293, 9 | 115280095190773, 10 | 115797848077099, 11 | 1099726899285419, 12 | ] 13 | 14 | 15 | def is_prime(n): 16 | if n < 2: 17 | return False 18 | if n == 2: 19 | return True 20 | if n % 2 == 0: 21 | return False 22 | 23 | sqrt_n = int(math.floor(math.sqrt(n))) 24 | for i in range(3, sqrt_n + 1, 2): 25 | if n % i == 0: 26 | return False 27 | return True 28 | 29 | 30 | if __name__ == "__main__": 31 | with concurrent.futures.ProcessPoolExecutor(4) as executor: 32 | for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): 33 | print("%d is prime: %s" % (number, prime)) 34 | -------------------------------------------------------------------------------- /Chapter 09/ex01.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def baz() -> str: 5 | print("Before Sleep") 6 | await asyncio.sleep(1) 7 | print("After Sleep") 8 | return "Hello world" 9 | 10 | 11 | async def main(): 12 | r = baz() 13 | print(r) 14 | result = await r 15 | print(result) 16 | 17 | 18 | if __name__ == "__main__": 19 | asyncio.run(main()) 20 | -------------------------------------------------------------------------------- /Chapter 09/ex02.py: -------------------------------------------------------------------------------- 1 | from time import sleep, time 2 | 3 | fake_users = [ 4 | { 5 | "id": 1, 6 | "name": "April Murphy", 7 | "company": "Bailey Inc", 8 | "email": "shawnlittle@example.org", 9 | }, 10 | { 11 | "id": 2, 12 | "name": "Emily Alexander", 13 | "company": "Martinez-Smith", 14 | "email": "turnerandrew@example.org", 15 | }, 16 | { 17 | "id": 3, 18 | "name": "Patrick Jones", 19 | "company": "Young, Pruitt and Miller", 20 | "email": "alancoleman@example.net", 21 | }, 22 | ] 23 | 24 | 25 | def get_user_sync(uid: int) -> dict: 26 | sleep(0.5) 27 | (user,) = list(filter(lambda user: user["id"] == uid, fake_users)) 28 | return user 29 | 30 | 31 | if __name__ == "__main__": 32 | start = time() 33 | for i in range(1, 4): 34 | print(get_user_sync(i)) 35 | print(time() - start) 36 | -------------------------------------------------------------------------------- /Chapter 09/ex03.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from time import time 3 | 4 | fake_users = [ 5 | { 6 | "id": 1, 7 | "name": "April Murphy", 8 | "company": "Bailey Inc", 9 | "email": "shawnlittle@example.org", 10 | }, 11 | { 12 | "id": 2, 13 | "name": "Emily Alexander", 14 | "company": "Martinez-Smith", 15 | "email": "turnerandrew@example.org", 16 | }, 17 | { 18 | "id": 3, 19 | "name": "Patrick Jones", 20 | "company": "Young, Pruitt and Miller", 21 | "email": "alancoleman@example.net", 22 | }, 23 | ] 24 | 25 | 26 | async def get_user_async(uid: int) -> dict: 27 | await asyncio.sleep(0.5) 28 | (user,) = list(filter(lambda user: user["id"] == uid, fake_users)) 29 | return user 30 | 31 | 32 | async def main(): 33 | r = [] 34 | for i in range(1, 4): 35 | r.append(get_user_async(i)) 36 | return await asyncio.gather(*r) 37 | 38 | 39 | if __name__ == "__main__": 40 | start = time() 41 | result = asyncio.run(main()) 42 | for r in result: 43 | print(r) 44 | print(time() - start) 45 | -------------------------------------------------------------------------------- /Chapter 09/ex04.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import random 3 | 4 | 5 | async def random_value(): 6 | print("start task") 7 | await asyncio.sleep(1) 8 | print("task finished") 9 | return random.random() 10 | 11 | 12 | async def main(): 13 | task = asyncio.create_task(random_value()) 14 | print("task scheduled") 15 | await task 16 | print(f"result: {task.result()}") 17 | 18 | 19 | if __name__ == "__main__": 20 | asyncio.run(main()) 21 | -------------------------------------------------------------------------------- /Chapter 09/ex05.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def faulty_task(): 5 | raise ValueError("Помилка у завданні") 6 | 7 | 8 | async def main(): 9 | task = asyncio.create_task(faulty_task()) 10 | 11 | try: 12 | await task 13 | except ValueError as e: 14 | print(f"Виняток під час виконання завдання: {e}") 15 | else: 16 | print(f"Завдання завершилося успішно: {task.result()}") 17 | 18 | 19 | if __name__ == "__main__": 20 | asyncio.run(main()) 21 | -------------------------------------------------------------------------------- /Chapter 09/ex06.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def long_running_task(): 5 | try: 6 | # Припустимо, ця операція триває довго 7 | await asyncio.sleep(10) 8 | return "Завдання завершено" 9 | except asyncio.CancelledError: 10 | print("Завдання було скасовано") 11 | raise 12 | 13 | 14 | async def main(): 15 | task = asyncio.create_task(long_running_task()) 16 | 17 | await asyncio.sleep(1) # Чекаємо деякий час перед скасуванням 18 | task.cancel() 19 | 20 | try: 21 | await task 22 | except asyncio.CancelledError: 23 | print("Головна програма: Завдання скасовано") 24 | 25 | 26 | if __name__ == "__main__": 27 | asyncio.run(main()) 28 | -------------------------------------------------------------------------------- /Chapter 09/ex07.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def my_task(): 5 | return "Результат завдання my_task" 6 | 7 | 8 | def my_callback(task): 9 | print("Завдання завершено з результатом:", task.result()) 10 | 11 | 12 | async def main(): 13 | task = asyncio.create_task(my_task()) 14 | task.add_done_callback(my_callback) 15 | r = await task 16 | print(r) 17 | 18 | 19 | if __name__ == "__main__": 20 | asyncio.run(main()) 21 | -------------------------------------------------------------------------------- /Chapter 09/ex08.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def task_one(): 5 | # Виконуємо якусь операцію 6 | await asyncio.sleep(1) 7 | return "результат task_one" 8 | 9 | 10 | async def task_two(): 11 | # Виконуємо іншу операцію 12 | await asyncio.sleep(2) 13 | return "результат task_two" 14 | 15 | 16 | async def main(): 17 | results = await asyncio.gather(task_one(), task_two()) 18 | print(results) 19 | 20 | 21 | if __name__ == "__main__": 22 | asyncio.run(main()) 23 | -------------------------------------------------------------------------------- /Chapter 09/ex09.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def task_one(): 5 | await asyncio.sleep(1) 6 | return "результат task_one" 7 | 8 | 9 | async def task_two(): 10 | await asyncio.sleep(2) 11 | return "результат task_two" 12 | 13 | 14 | async def main(): 15 | tasks = [asyncio.create_task(task) for task in [task_one(), task_two()]] 16 | done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) 17 | for task in done: 18 | print("Завершено:", task.result()) 19 | 20 | 21 | if __name__ == "__main__": 22 | asyncio.run(main()) 23 | -------------------------------------------------------------------------------- /Chapter 09/ex10.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def long_running_task(): 5 | await asyncio.sleep(5) # Припустимо, що ця операція триває 5 секунд 6 | return "Завдання завершено" 7 | 8 | 9 | async def main(): 10 | try: 11 | # Чекаємо завершення завдання протягом максимум 3 секунд 12 | result = await asyncio.wait_for(long_running_task(), timeout=3) 13 | print(result) 14 | except asyncio.TimeoutError: 15 | print("Завдання не було завершено вчасно") 16 | 17 | 18 | if __name__ == "__main__": 19 | asyncio.run(main()) 20 | -------------------------------------------------------------------------------- /Chapter 09/ex11.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import concurrent.futures 3 | from time import time 4 | 5 | 6 | def blocks(n): 7 | counter = n 8 | start = time() 9 | while counter > 0: 10 | counter -= 1 11 | return time() - start 12 | 13 | 14 | async def monitoring(): 15 | while True: 16 | await asyncio.sleep(2) 17 | print(f"Monitoring {time()}") 18 | 19 | 20 | async def run_blocking_tasks(executor, n): 21 | loop = asyncio.get_event_loop() 22 | print("waiting for executor tasks") 23 | result = await loop.run_in_executor(executor, blocks, n) 24 | return result 25 | 26 | 27 | async def main(): 28 | asyncio.create_task(monitoring()) 29 | with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor: 30 | futures = [ 31 | run_blocking_tasks(executor, n) 32 | for n in [50_000_000, 60_000_000, 70_000_000] 33 | ] 34 | results = await asyncio.gather(*futures) 35 | return results 36 | 37 | 38 | if __name__ == "__main__": 39 | result = asyncio.run(main()) 40 | for r in result: 41 | print(r) 42 | -------------------------------------------------------------------------------- /Chapter 09/ex12.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from time import time 3 | 4 | urls = ["http://www.google.com", "http://www.python.org", "http://duckduckgo.com"] 5 | 6 | 7 | def preview_fetch(url): 8 | r = requests.get(url) 9 | return url, r.text[:150] 10 | 11 | 12 | if __name__ == "__main__": 13 | start = time() 14 | for url in urls: 15 | r = preview_fetch(url) 16 | print(r) 17 | print(time() - start) 18 | -------------------------------------------------------------------------------- /Chapter 09/ex13.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import requests 3 | from concurrent.futures import ThreadPoolExecutor 4 | from time import time 5 | 6 | urls = ["http://www.google.com", "http://www.python.org", "http://duckduckgo.com"] 7 | 8 | 9 | def preview_fetch(url): 10 | r = requests.get(url) 11 | return url, r.text[:150] 12 | 13 | 14 | async def preview_fetch_async(): 15 | loop = asyncio.get_running_loop() 16 | 17 | with ThreadPoolExecutor(3) as pool: 18 | futures = [loop.run_in_executor(pool, preview_fetch, url) for url in urls] 19 | result = await asyncio.gather(*futures, return_exceptions=True) 20 | return result 21 | 22 | 23 | if __name__ == "__main__": 24 | start = time() 25 | r = asyncio.run(preview_fetch_async()) 26 | print(r) 27 | print(time() - start) 28 | -------------------------------------------------------------------------------- /Chapter 09/ex14.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiofile import async_open 3 | 4 | 5 | async def main(): 6 | async with async_open("hello.txt", "w+") as afp: 7 | await afp.write("Hello ") 8 | await afp.write("world\n") 9 | await afp.write("Hello from - async world!") 10 | 11 | 12 | if __name__ == "__main__": 13 | asyncio.run(main()) 14 | -------------------------------------------------------------------------------- /Chapter 09/ex15.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiofile import async_open 3 | 4 | 5 | async def main(): 6 | async with async_open("hello.txt", "r") as afp: 7 | print(await afp.read()) 8 | 9 | 10 | if __name__ == "__main__": 11 | asyncio.run(main()) 12 | -------------------------------------------------------------------------------- /Chapter 09/ex16.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiofile import AIOFile, LineReader 3 | 4 | 5 | async def main(): 6 | async with AIOFile("hello.txt", "r") as afp: 7 | async for line in LineReader(afp): 8 | print(line) 9 | 10 | 11 | if __name__ == "__main__": 12 | asyncio.run(main()) 13 | -------------------------------------------------------------------------------- /Chapter 09/ex17.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiopath import AsyncPath 3 | 4 | 5 | async def main(): 6 | apath = AsyncPath("hello.txt") 7 | print(await apath.exists()) 8 | print(await apath.is_file()) 9 | print(await apath.is_dir()) 10 | 11 | 12 | if __name__ == "__main__": 13 | asyncio.run(main()) 14 | -------------------------------------------------------------------------------- /Chapter 09/ex18.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiopath import AsyncPath 3 | from aioshutil import copyfile 4 | 5 | 6 | async def main(): 7 | apath = AsyncPath("hello.txt") 8 | if await apath.exists(): 9 | new_path = AsyncPath("logs") 10 | await new_path.mkdir(exist_ok=True, parents=True) 11 | await copyfile(apath, new_path / apath) 12 | 13 | 14 | if __name__ == "__main__": 15 | asyncio.run(main()) 16 | -------------------------------------------------------------------------------- /Chapter 10/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goitacademy/Computer-Systems-and-Their-Fundamentals/136438ed72ad32ec2ccd8fe6bed68c8ca396c282/Chapter 10/.gitkeep -------------------------------------------------------------------------------- /Chapter 10/map-reduce01.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def map_function(text): 5 | words = text.split() 6 | return [(word, 1) for word in words] 7 | 8 | 9 | def shuffle_function(mapped_values): 10 | shuffled = defaultdict(list) 11 | for key, value in mapped_values: 12 | shuffled[key].append(value) 13 | return shuffled.items() 14 | 15 | 16 | def reduce_function(shuffled_values): 17 | reduced = {} 18 | for key, values in shuffled_values: 19 | reduced[key] = sum(values) 20 | return reduced 21 | 22 | 23 | # Виконання MapReduce 24 | def map_reduce(text): 25 | # Крок 1: Маппінг 26 | mapped_values = map_function(text) 27 | 28 | # Крок 2: Shuffle 29 | shuffled_values = shuffle_function(mapped_values) 30 | 31 | # Крок 3: Редукція 32 | reduced_values = reduce_function(shuffled_values) 33 | 34 | return reduced_values 35 | 36 | 37 | if __name__ == "__main__": 38 | # Вхідний текст для обробки 39 | text = "hello world hello Python hello Student" 40 | 41 | # Виконання MapReduce на вхідному тексті 42 | result = map_reduce(text) 43 | 44 | print("Результат підрахунку слів:", result) 45 | -------------------------------------------------------------------------------- /Chapter 10/map-reduce02.py: -------------------------------------------------------------------------------- 1 | from concurrent.futures import ThreadPoolExecutor 2 | from collections import defaultdict 3 | 4 | 5 | def map_function(word): 6 | return word, 1 7 | 8 | 9 | def shuffle_function(mapped_values): 10 | shuffled = defaultdict(list) 11 | for key, value in mapped_values: 12 | shuffled[key].append(value) 13 | return shuffled.items() 14 | 15 | 16 | def reduce_function(key_values): 17 | key, values = key_values 18 | return key, sum(values) 19 | 20 | 21 | # Виконання MapReduce 22 | def map_reduce(text): 23 | words = text.split() 24 | 25 | # Паралельний Маппінг 26 | with ThreadPoolExecutor() as executor: 27 | mapped_values = list(executor.map(map_function, words)) 28 | 29 | # Крок 2: Shuffle 30 | shuffled_values = shuffle_function(mapped_values) 31 | 32 | # Паралельна Редукція 33 | with ThreadPoolExecutor() as executor: 34 | reduced_values = list(executor.map(reduce_function, shuffled_values)) 35 | 36 | return dict(reduced_values) 37 | 38 | 39 | if __name__ == "__main__": 40 | # Вхідний текст для обробки 41 | text = "hello world hello Python hello Student" 42 | 43 | # Виконання MapReduce на вхідному тексті 44 | result = map_reduce(text) 45 | 46 | print("Результат підрахунку слів:", result) 47 | -------------------------------------------------------------------------------- /Chapter 10/map-reduce03.py: -------------------------------------------------------------------------------- 1 | from concurrent.futures import ThreadPoolExecutor 2 | from collections import defaultdict 3 | 4 | import requests 5 | 6 | 7 | def get_text(url): 8 | try: 9 | response = requests.get(url) 10 | response.raise_for_status() # Перевірка на помилки HTTP 11 | return response.text 12 | except requests.RequestException as e: 13 | return None 14 | 15 | 16 | def map_function(word): 17 | return word, 1 18 | 19 | 20 | def shuffle_function(mapped_values): 21 | shuffled = defaultdict(list) 22 | for key, value in mapped_values: 23 | shuffled[key].append(value) 24 | return shuffled.items() 25 | 26 | 27 | def reduce_function(key_values): 28 | key, values = key_values 29 | return key, sum(values) 30 | 31 | 32 | # Виконання MapReduce 33 | def map_reduce(text): 34 | words = text.split() 35 | 36 | # Паралельний Маппінг 37 | with ThreadPoolExecutor() as executor: 38 | mapped_values = list(executor.map(map_function, words)) 39 | 40 | # Крок 2: Shuffle 41 | shuffled_values = shuffle_function(mapped_values) 42 | 43 | # Паралельна Редукція 44 | with ThreadPoolExecutor() as executor: 45 | reduced_values = list(executor.map(reduce_function, shuffled_values)) 46 | 47 | return dict(reduced_values) 48 | 49 | 50 | if __name__ == "__main__": 51 | # Вхідний текст для обробки 52 | url = "https://gutenberg.net.au/ebooks01/0100021.txt" 53 | text = get_text(url) 54 | if text: 55 | # Виконання MapReduce на вхідному тексті 56 | result = map_reduce(text) 57 | 58 | print("Результат підрахунку слів:", result) 59 | else: 60 | print("Помилка: Не вдалося отримати вхідний текст.") 61 | -------------------------------------------------------------------------------- /Chapter 10/map-reduce04.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | from concurrent.futures import ThreadPoolExecutor 4 | from collections import defaultdict 5 | 6 | import requests 7 | 8 | 9 | def get_text(url): 10 | try: 11 | response = requests.get(url) 12 | response.raise_for_status() # Перевірка на помилки HTTP 13 | return response.text 14 | except requests.RequestException as e: 15 | return None 16 | 17 | 18 | # Функція для видалення знаків пунктуації 19 | def remove_punctuation(text): 20 | return text.translate(str.maketrans("", "", string.punctuation)) 21 | 22 | 23 | def map_function(word): 24 | return word, 1 25 | 26 | 27 | def shuffle_function(mapped_values): 28 | shuffled = defaultdict(list) 29 | for key, value in mapped_values: 30 | shuffled[key].append(value) 31 | return shuffled.items() 32 | 33 | 34 | def reduce_function(key_values): 35 | key, values = key_values 36 | return key, sum(values) 37 | 38 | 39 | # Виконання MapReduce 40 | def map_reduce(text, search_words=None): 41 | # Видалення знаків пунктуації 42 | text = remove_punctuation(text) 43 | words = text.split() 44 | 45 | # Якщо задано список слів для пошуку, враховувати тільки ці слова 46 | if search_words: 47 | words = [word for word in words if word in search_words] 48 | 49 | # Паралельний Маппінг 50 | with ThreadPoolExecutor() as executor: 51 | mapped_values = list(executor.map(map_function, words)) 52 | 53 | # Крок 2: Shuffle 54 | shuffled_values = shuffle_function(mapped_values) 55 | 56 | # Паралельна Редукція 57 | with ThreadPoolExecutor() as executor: 58 | reduced_values = list(executor.map(reduce_function, shuffled_values)) 59 | 60 | return dict(reduced_values) 61 | 62 | 63 | if __name__ == "__main__": 64 | # Вхідний текст для обробки 65 | url = "https://gutenberg.net.au/ebooks01/0100021.txt" 66 | text = get_text(url) 67 | if text: 68 | # Виконання MapReduce на вхідному тексті 69 | search_words = ["war", "peace", "love"] 70 | result = map_reduce(text, search_words) 71 | 72 | print("Результат підрахунку слів:", result) 73 | else: 74 | print("Помилка: Не вдалося отримати вхідний текст.") 75 | -------------------------------------------------------------------------------- /Chapter 10/map01.py: -------------------------------------------------------------------------------- 1 | numbers = [1, 2, 3, 4, 5] 2 | 3 | for i in map(lambda x: x**2, numbers): 4 | print(i) 5 | -------------------------------------------------------------------------------- /Chapter 10/map02.py: -------------------------------------------------------------------------------- 1 | numbers = [1, 2, 3, 4, 5] 2 | 3 | squared_nums = list(map(lambda x: x**2, numbers)) 4 | print(squared_nums) 5 | -------------------------------------------------------------------------------- /Chapter 10/map03.py: -------------------------------------------------------------------------------- 1 | nums1 = [1, 2, 3] 2 | nums2 = [4, 5, 6] 3 | sum_nums = map(lambda x, y: x + y, nums1, nums2) 4 | 5 | print(list(sum_nums)) 6 | -------------------------------------------------------------------------------- /Chapter 10/map04.py: -------------------------------------------------------------------------------- 1 | numbers = [1, 2, 3, 4, 5] 2 | 3 | squared_nums = list(map(lambda x: x**2, numbers)) 4 | print(squared_nums) 5 | 6 | nums = [1, 2, 3, 4, 5] 7 | squared_nums = [x * x for x in nums] 8 | print(squared_nums) 9 | -------------------------------------------------------------------------------- /Chapter 10/reduce01.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | 3 | # Приклад 1: Обчислення суми всіх елементів списку 4 | numbers = [1, 2, 3, 4, 5] 5 | sum_result = reduce(lambda x, y: x + y, numbers) 6 | print(sum_result) # Виведе 15 (1 + 2 + 3 + 4 + 5 = 15) 7 | 8 | # Приклад 2: Об'єднання рядка зі списку рядків 9 | words = ["Hello", "World", "Python"] 10 | sentence = reduce(lambda x, y: x + " " + y, words) 11 | print(sentence) # Виведе "Hello World Python" 12 | 13 | # Приклад 3: Знаходження максимального числа в списку 14 | numbers = [10, 4, 25, 7, 31] 15 | max_num = reduce(lambda x, y: x if x > y else y, numbers) 16 | print(max_num) # Виведе 31 (максимальне число в списку) 17 | -------------------------------------------------------------------------------- /Chapter 10/reduce02.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | 3 | result = reduce((lambda x, y: x * y), [1, 2, 3, 4]) 4 | 5 | print(result) # 24 6 | -------------------------------------------------------------------------------- /Chapter 10/reduce03.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | 3 | result = reduce((lambda x, y: x * y), [1, 2, 3, 4], 3) 4 | 5 | print(result) # 72 6 | -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | Personal site 16 | 17 | 18 |
19 | 31 |
32 |
33 |
39 |

Write to me

40 |
41 | 42 | 43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 |
52 |
53 | 56 | 59 |
60 |
61 |
62 |
63 |
64 | 65 | 66 | -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | Personal site 16 | 17 | 18 |
19 | 31 |
32 | 404: Not found 33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/images/gupalo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goitacademy/Computer-Systems-and-Their-Fundamentals/136438ed72ad32ec2ccd8fe6bed68c8ca396c282/Chapter 11/HTTP_Server/images/gupalo.jpg -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | Personal site 16 | 17 | 18 |
19 | 31 |
32 |
33 | ... 40 |
Gupalo Vasyl
41 |
42 |
43 |

44 | My name is Vasyl. I live in the center of Ukraine in the city called Poltava. With the appearance of 45 | internet, I got so interested with it, that I almost live only in virtual space. Recently (for about two 46 | years now) this isn't just a hobby, but also a good earnings for me and my family. Of course, I'm not 47 | going to stop only on this, I will continue to try achieve even better results! Internet community is 48 | very interesting and multifaceted, almost every day something new appears, and you want to study it, 49 | implement and test it on yourself. 50 |

51 |
52 |
53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/main.py: -------------------------------------------------------------------------------- 1 | import mimetypes 2 | import pathlib 3 | from http.server import HTTPServer, BaseHTTPRequestHandler 4 | import urllib.parse 5 | 6 | 7 | class HttpHandler(BaseHTTPRequestHandler): 8 | def do_POST(self): 9 | data = self.rfile.read(int(self.headers['Content-Length'])) 10 | print(data) 11 | data_parse = urllib.parse.unquote_plus(data.decode()) 12 | print(data_parse) 13 | data_dict = {key: value for key, value in [el.split('=') for el in data_parse.split('&')]} 14 | print(data_dict) 15 | self.send_response(302) 16 | self.send_header('Location', '/') 17 | self.end_headers() 18 | 19 | def do_GET(self): 20 | pr_url = urllib.parse.urlparse(self.path) 21 | if pr_url.path == '/': 22 | self.send_html_file('index.html') 23 | elif pr_url.path == '/contact': 24 | self.send_html_file('contact.html') 25 | else: 26 | if pathlib.Path().joinpath(pr_url.path[1:]).exists(): 27 | self.send_static() 28 | else: 29 | self.send_html_file('error.html', 404) 30 | 31 | def send_html_file(self, filename, status=200): 32 | self.send_response(status) 33 | self.send_header('Content-type', 'text/html') 34 | self.end_headers() 35 | with open(filename, 'rb') as fd: 36 | self.wfile.write(fd.read()) 37 | 38 | def send_static(self): 39 | self.send_response(200) 40 | mt = mimetypes.guess_type(self.path) 41 | if mt: 42 | self.send_header("Content-type", mt[0]) 43 | else: 44 | self.send_header("Content-type", 'text/plain') 45 | self.end_headers() 46 | with open(f'.{self.path}', 'rb') as file: 47 | self.wfile.write(file.read()) 48 | 49 | 50 | def run(server_class=HTTPServer, handler_class=HttpHandler): 51 | server_address = ('', 8000) 52 | http = server_class(server_address, handler_class) 53 | try: 54 | http.serve_forever() 55 | except KeyboardInterrupt: 56 | http.server_close() 57 | 58 | 59 | if __name__ == '__main__': 60 | run() 61 | -------------------------------------------------------------------------------- /Chapter 11/HTTP_Server/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto:300,400,700&subset=cyrillic'); 2 | 3 | body { 4 | margin: 0; 5 | padding: 0; 6 | font-family: 'Roboto', Arial, Helvetica, sans-serif; 7 | background-color: #d0f1f6; 8 | } -------------------------------------------------------------------------------- /Chapter 11/request01.py: -------------------------------------------------------------------------------- 1 | import urllib.request 2 | 3 | 4 | with urllib.request.urlopen("https://www.python.org/") as f: 5 | print(f.read(300)) 6 | -------------------------------------------------------------------------------- /Chapter 11/request02.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | 4 | r = requests.get("https://api.github.com/events") 5 | print(r.text[:300]) 6 | -------------------------------------------------------------------------------- /Chapter 11/request03.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | response = requests.get( 4 | "https://api.privatbank.ua/p24api/pubinfo?exchange&json&coursid=11" 5 | ) 6 | exchange_rate = response.json() 7 | print(exchange_rate) 8 | -------------------------------------------------------------------------------- /Chapter 11/simple_http_server.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | from time import sleep 3 | from http import client 4 | from http.server import HTTPServer, BaseHTTPRequestHandler 5 | 6 | 7 | class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): 8 | def do_GET(self): 9 | self.send_response(200) 10 | self.end_headers() 11 | self.wfile.write(b"Hello, world!") 12 | 13 | def do_POST(self): 14 | pass 15 | 16 | 17 | httpd = HTTPServer(("localhost", 8001), SimpleHTTPRequestHandler) 18 | server = Thread(target=httpd.serve_forever) 19 | server.start() 20 | sleep(0.5) 21 | 22 | h1 = client.HTTPConnection("localhost", 8001) 23 | h1.request("GET", "/") 24 | 25 | res = h1.getresponse() 26 | print(res.status, res.reason) 27 | data = res.read() 28 | print(data) 29 | 30 | httpd.shutdown() 31 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/client_TCP_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | TCP_IP = "localhost" 4 | TCP_PORT = 8080 5 | MESSAGE = "Python Web development" 6 | 7 | 8 | def run_client(ip: str, port: int): 9 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 10 | server = ip, port 11 | sock.connect(server) 12 | print(f"Connection established {server}") 13 | for line in MESSAGE.split(" "): 14 | print(f"Send data: {line}") 15 | sock.send(line.encode()) 16 | response = sock.recv(1024) 17 | print(f"Response data: {response.decode()}") 18 | print(f"Data transfer completed") 19 | 20 | 21 | if __name__ == "__main__": 22 | run_client(TCP_IP, TCP_PORT) 23 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/client_UDP_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | UDP_IP = "127.0.0.1" 4 | UDP_PORT = 8080 5 | MESSAGE = "Python Web development" 6 | 7 | 8 | def run_client(ip, port): 9 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 10 | server = ip, port 11 | for line in MESSAGE.split(" "): 12 | data = line.encode() 13 | sock.sendto(data, server) 14 | print(f"Send data: {data.decode()} to server: {server}") 15 | response, address = sock.recvfrom(1024) 16 | print(f"Response data: {response.decode()} from address: {address}") 17 | sock.close() 18 | 19 | 20 | if __name__ == "__main__": 21 | run_client(UDP_IP, UDP_PORT) 22 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/client_chat_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import signal 4 | 5 | # Вибір нікнейму 6 | nickname = None 7 | 8 | # Підключення до сервера 9 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 | client.connect(("127.0.0.1", 12345)) 11 | 12 | # Змінна для контролю потоку 13 | running = True 14 | 15 | 16 | def handle_signal(signum, frame): 17 | global running 18 | running = False 19 | client.close() 20 | print("\nЗавершення програми...") 21 | 22 | 23 | # Прослуховування сервера та відправка нікнейму 24 | def receive(): 25 | global running 26 | while running: 27 | try: 28 | # Отримання повідомлення від сервера 29 | message = client.recv(1024).decode("utf-8") 30 | if message == "NICK": 31 | client.send(nickname.encode("utf-8")) 32 | else: 33 | print(message) 34 | except socket.error: 35 | # Закриття з'єднання при виникненні помилки 36 | print("Помилка з'єднання з сервером, не вдалося отримати повідомлення!") 37 | running = False 38 | break 39 | 40 | 41 | # Відправка повідомлень серверу 42 | def write(): 43 | global running 44 | while running: 45 | try: 46 | message = input(">>> ") 47 | if message.lower() == "exit": 48 | client.send(f"{nickname} вийшов із чату.".encode("utf-8")) 49 | running = False 50 | break 51 | message = f"{nickname}: {message}" 52 | client.send(message.encode("utf-8")) 53 | except (EOFError, KeyboardInterrupt): 54 | try: 55 | client.send(f"{nickname} вийшов із чату.".encode("utf-8")) 56 | except socket.error: 57 | pass 58 | client.close() 59 | running = False 60 | break 61 | except socket.error: 62 | print(f"Помилка з'єднання із сервером!") 63 | running = False 64 | break 65 | 66 | 67 | if __name__ == "__main__": 68 | nickname = input("Виберіть нікнейм: ") 69 | signal.signal(signal.SIGINT, handle_signal) 70 | signal.signal(signal.SIGTERM, handle_signal) 71 | 72 | # Запуск потоків для прослуховування та письма 73 | receive_thread = threading.Thread(target=receive) 74 | receive_thread.start() 75 | 76 | write_thread = threading.Thread(target=write) 77 | write_thread.start() 78 | 79 | receive_thread.join() 80 | write_thread.join() 81 | client.close() 82 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/server_TCP_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from concurrent import futures as cf 3 | 4 | TCP_IP = "localhost" 5 | TCP_PORT = 8080 6 | 7 | 8 | def run_server(ip, port): 9 | def handle(sock: socket.socket, address: str): 10 | print(f"Connection established {address}") 11 | while True: 12 | received = sock.recv(1024) 13 | if not received: 14 | break 15 | data = received.decode() 16 | print(f"Data received: {data}") 17 | sock.send(received) 18 | print(f"Socket connection closed {address}") 19 | sock.close() 20 | 21 | server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | server_socket.bind((ip, port)) 23 | server_socket.listen(10) 24 | print(f"Start echo server {server_socket.getsockname()}") 25 | with cf.ThreadPoolExecutor(10) as client_pool: 26 | try: 27 | while True: 28 | new_sock, address = server_socket.accept() 29 | client_pool.submit(handle, new_sock, address) 30 | except KeyboardInterrupt: 31 | print(f"Destroy server") 32 | finally: 33 | server_socket.close() 34 | 35 | 36 | if __name__ == "__main__": 37 | run_server(TCP_IP, TCP_PORT) 38 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/server_UDP_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | UDP_IP = "127.0.0.1" 4 | UDP_PORT = 8080 5 | 6 | 7 | def run_server(ip, port): 8 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 9 | server = ip, port 10 | sock.bind(server) 11 | try: 12 | while True: 13 | data, address = sock.recvfrom(1024) 14 | print(f"Received data: {data.decode()} from: {address}") 15 | sock.sendto(data, address) 16 | print(f"Send data: {data.decode()} to: {address}") 17 | 18 | except KeyboardInterrupt: 19 | print(f"Destroy server") 20 | finally: 21 | sock.close() 22 | 23 | 24 | if __name__ == "__main__": 25 | run_server(UDP_IP, UDP_PORT) 26 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/server_chat_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | 4 | # Налаштування сервера 5 | host = "127.0.0.1" # Локальна адреса 6 | port = 12345 # Порт для прослуховування 7 | 8 | # Створення сокета 9 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 | server.bind((host, port)) 11 | server.listen() 12 | 13 | # Список клієнтів та їхні нікнейми 14 | clients = [] 15 | nicknames = [] 16 | 17 | 18 | # Відправка повідомлень усім підключеним клієнтам 19 | def broadcast(message): 20 | for client in clients: 21 | client.send(message) 22 | 23 | 24 | # Обробка повідомлень від клієнтів 25 | def handle(client): 26 | while True: 27 | try: 28 | # Отримання повідомлень від клієнта 29 | message = client.recv(1024) 30 | broadcast(message) 31 | except: 32 | # Видалення та закриття клієнтів при виникненні помилки 33 | index = clients.index(client) 34 | clients.remove(client) 35 | client.close() 36 | nickname = nicknames[index] 37 | broadcast(f"{nickname} вийшов з чату!".encode("utf-8")) 38 | nicknames.remove(nickname) 39 | break 40 | 41 | 42 | # Основна функція для прийняття клієнтів 43 | def receive(): 44 | while True: 45 | client, address = server.accept() 46 | print(f"Підключено з {str(address)}") 47 | 48 | # Запит нікнейму 49 | client.send("NICK".encode("utf-8")) 50 | nickname = client.recv(1024).decode("utf-8") 51 | nicknames.append(nickname) 52 | clients.append(client) 53 | 54 | print(f"Нікнейм клієнта: {nickname}") 55 | broadcast(f"{nickname} приєднався до чату!".encode("utf-8")) 56 | client.send("Підключено до сервера!".encode("utf-8")) 57 | 58 | # Початок обробки потоку для клієнта 59 | thread = threading.Thread(target=handle, args=(client,)) 60 | thread.start() 61 | 62 | 63 | if __name__ == "__main__": 64 | print("Сервер запущено...") 65 | receive() 66 | -------------------------------------------------------------------------------- /Chapter 12/Socket_examples/simple_socket_server.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | from time import sleep 4 | 5 | 6 | def echo_server(host, port): 7 | with socket.socket() as s: 8 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 9 | s.bind((host, port)) 10 | s.listen(1) 11 | conn, addr = s.accept() 12 | print(f"Connected by {addr}") 13 | with conn: 14 | while True: 15 | data = conn.recv(1024) 16 | print(f"From client: {data}") 17 | if not data: 18 | break 19 | conn.send(data.upper()) 20 | 21 | 22 | def simple_client(host, port): 23 | with socket.socket() as s: 24 | while True: 25 | try: 26 | s.connect((host, port)) 27 | s.sendall(b"Hello, world") 28 | data = s.recv(1024) 29 | print(f"From server: {data}") 30 | break 31 | except ConnectionRefusedError: 32 | sleep(0.5) 33 | 34 | 35 | if __name__ == "__main__": 36 | HOST = "127.0.0.1" 37 | PORT = 55555 38 | 39 | server = threading.Thread(target=echo_server, args=(HOST, PORT)) 40 | client = threading.Thread(target=simple_client, args=(HOST, PORT)) 41 | 42 | server.start() 43 | client.start() 44 | server.join() 45 | client.join() 46 | print("Done!") 47 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/chat/main.css: -------------------------------------------------------------------------------- 1 | input[type='text'] { 2 | width: 300px; 3 | border: 1px solid lightseagreen; 4 | padding: 5px 10px; 5 | color: darkred; 6 | font-size: 16px; 7 | font-family: 'Cambria', 'Cochin', 'Georgia', 'Times', 'Times New Roman', serif; 8 | } 9 | 10 | button { 11 | border: 1px solid #ccc; 12 | padding: 5px 10px; 13 | font-size: 16px; 14 | } 15 | 16 | #subscribe { 17 | color: darkblue; 18 | font-size: 14px; 19 | font-family: 'Courier New', 'Courier', monospace; 20 | margin-top: 20px; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/chat/main.js: -------------------------------------------------------------------------------- 1 | console.log('Hello world!') 2 | 3 | const ws = new WebSocket('ws://localhost:8080') 4 | 5 | formChat.addEventListener('submit', (e) => { 6 | e.preventDefault() 7 | ws.send(textField.value) 8 | textField.value = null 9 | }) 10 | 11 | ws.onopen = (e) => { 12 | console.log('Hello WebSocket!') 13 | } 14 | 15 | ws.onmessage = (e) => { 16 | console.log(e.data) 17 | text = e.data 18 | 19 | const elMsg = document.createElement('div') 20 | elMsg.textContent = text 21 | subscribe.appendChild(elMsg) 22 | } 23 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/chat/server.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import websockets 4 | import names 5 | from websockets import WebSocketServerProtocol 6 | from websockets.exceptions import ConnectionClosedOK 7 | 8 | logging.basicConfig(level=logging.INFO) 9 | 10 | 11 | class Server: 12 | clients = set() 13 | 14 | async def register(self, ws: WebSocketServerProtocol): 15 | ws.name = names.get_full_name() 16 | self.clients.add(ws) 17 | logging.info(f"{ws.remote_address} connects") 18 | 19 | async def unregister(self, ws: WebSocketServerProtocol): 20 | self.clients.remove(ws) 21 | logging.info(f"{ws.remote_address} disconnects") 22 | 23 | async def send_to_clients(self, message: str): 24 | if self.clients: 25 | [await client.send(message) for client in self.clients] 26 | 27 | async def ws_handler(self, ws: WebSocketServerProtocol): 28 | await self.register(ws) 29 | try: 30 | await self.distrubute(ws) 31 | except ConnectionClosedOK: 32 | pass 33 | finally: 34 | await self.unregister(ws) 35 | 36 | async def distrubute(self, ws: WebSocketServerProtocol): 37 | async for message in ws: 38 | await self.send_to_clients(f"{ws.name}: {message}") 39 | 40 | 41 | async def main(): 42 | server = Server() 43 | async with websockets.serve(server.ws_handler, "localhost", 8080): 44 | await asyncio.Future() # run forever 45 | 46 | 47 | if __name__ == "__main__": 48 | asyncio.run(main()) 49 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | WebSocker Client 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 45 | 46 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/permanent_connection/consumer.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import websockets 4 | 5 | logging.basicConfig(level=logging.INFO) 6 | 7 | 8 | async def consumer(hostname: str, port: int): 9 | ws_resource_url = f"ws://{hostname}:{port}" 10 | async with websockets.connect(ws_resource_url) as ws: 11 | async for message in ws: 12 | logging.info(f"Message: {message}") 13 | 14 | 15 | if __name__ == "__main__": 16 | asyncio.run(consumer("localhost", 4000)) 17 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/permanent_connection/producer.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | import sys 4 | 5 | 6 | async def producer(message: str, host: str, port: int): 7 | async with websockets.connect(f"ws://{host}:{port}") as ws: 8 | await ws.send(message) 9 | 10 | 11 | if __name__ == "__main__": 12 | asyncio.run(producer(message=sys.argv[1], host="localhost", port=4000)) 13 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/permanent_connection/server.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import websockets 4 | from websockets import WebSocketServerProtocol 5 | from websockets.exceptions import ConnectionClosedOK 6 | 7 | logging.basicConfig(level=logging.INFO) 8 | 9 | 10 | class Server: 11 | clients = set() 12 | 13 | async def register(self, ws: WebSocketServerProtocol): 14 | self.clients.add(ws) 15 | logging.info(f"{ws.remote_address} connects") 16 | 17 | async def unregister(self, ws: WebSocketServerProtocol): 18 | self.clients.remove(ws) 19 | logging.info(f"{ws.remote_address} disconnects") 20 | 21 | async def send_to_clients(self, message: str): 22 | if self.clients: 23 | [await client.send(message) for client in self.clients] 24 | 25 | async def ws_handler(self, ws: WebSocketServerProtocol): 26 | await self.register(ws) 27 | try: 28 | await self.distrubute(ws) 29 | except ConnectionClosedOK: 30 | pass 31 | finally: 32 | await self.unregister(ws) 33 | 34 | async def distrubute(self, ws: WebSocketServerProtocol): 35 | async for message in ws: 36 | await self.send_to_clients(message) 37 | 38 | 39 | async def main(): 40 | server = Server() 41 | async with websockets.serve(server.ws_handler, "localhost", 4000): 42 | await asyncio.Future() # run forever 43 | 44 | 45 | if __name__ == "__main__": 46 | asyncio.run(main()) 47 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/server.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | 4 | 5 | async def handler(websocket, path): 6 | data = await websocket.recv() 7 | reply = f"Data recieved as: {data}!" 8 | print(reply) 9 | await websocket.send(reply) 10 | 11 | 12 | async def main(): 13 | async with websockets.serve(handler, "localhost", 8000): 14 | await asyncio.Future() # run forever 15 | 16 | 17 | if __name__ == "__main__": 18 | asyncio.run(main()) 19 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/simple_client.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | 4 | 5 | async def hello(): 6 | uri = "ws://localhost:8765" 7 | async with websockets.connect(uri) as websocket: 8 | name = input("What's your name? ") 9 | 10 | await websocket.send(name) 11 | print(f">>> {name}") 12 | 13 | greeting = await websocket.recv() 14 | print(f"<<< {greeting}") 15 | 16 | 17 | if __name__ == "__main__": 18 | asyncio.run(hello()) 19 | -------------------------------------------------------------------------------- /Chapter 12/WebSockets_examples/simple_server.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | 4 | 5 | async def hello(websocket): 6 | name = await websocket.recv() 7 | print(f"<<< {name}") 8 | 9 | greeting = f"Hello {name}!" 10 | 11 | await websocket.send(greeting) 12 | print(f">>> {greeting}") 13 | 14 | 15 | async def main(): 16 | async with websockets.serve(hello, "localhost", 8765): 17 | await asyncio.Future() # run forever 18 | 19 | 20 | if __name__ == "__main__": 21 | asyncio.run(main()) 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Computer Systems and Their Fundamentals 2 | 3 | *Description*: This core course equips the student with knowledge of **database management systems**, **operating systems and computer networks**. At the end of the course, students will have a critical understanding of the **architecture of computers and networks**, as well as how programs interact with these.  Students begin with mapping data storage problems (as they had done in Relational Databases) to understand how data is stored in a distributed network, and related issues such as concurrency.  Subsequently, students cover **operating systems** with an overview of process scheduling, process synchronization and memory management techniques with disk scheduling. The module concludes with **computer networks**, where we will be discussing all of the computer network layers and their protocols in detail. 4 | 5 | ### Модуль 1. Архітектура комп'ютерів 6 | 7 | - [Chapter 01](./Chapter%2001/) - Тема 1 Вступ до архітектури комп'ютерів 8 | - [Chapter 02](./Chapter%2002/) - Тема 2 Вступ до компіляторів та інтерпретаторів 9 | 10 | ### Модуль 2. Основи операційних систем 11 | 12 | - [Chapter 03](./Chapter%2003/) - Тема 3 Основи операційних систем 13 | - [Chapter 04](./Chapter%2004/) - Тема 4 Введення в Docker та контейнеризацію 14 | 15 | ### Модуль 3. Введення до вивчення систем управління базами даних 16 | 17 | - [Chapter 05](./Chapter%2005/) - Тема 5. Робота з реляційними базами даних 18 | - [Chapter 06](./Chapter%2006/) - Тема 6 Робота з NoSQL та MongoDB 19 | 20 | ### Модуль 4. Конкурентність і паралелізм 21 | 22 | - [Chapter 07](./Chapter%2007/) - Тема 7. Основи багатопотокового програмування 23 | - [Chapter 08](./Chapter%2008/) - Тема 8. Основи багатопроцесорного програмування 24 | 25 | ### Модуль 5. Асинхронна обробка 26 | 27 | - [Chapter 09](./Chapter%2009/) - Тема 9 Асинхронне програмування 28 | - [Chapter 10](./Chapter%2010/) - Тема 10 Введення в паралельні обчислення 29 | 30 | ### Модуль 6. Комп'ютерні мережі 31 | 32 | - [Chapter 11](./Chapter%2011/) - Тема 11 Основи комп'ютерних мереж та протоколи 33 | - [Chapter 12](./Chapter%2012/) - Тема 12 Socket Programming та реальний час комунікацій 34 | --------------------------------------------------------------------------------