Version française de ma réponse sur Stack Overflow : Socket - Screen sharing in Python.

Comment partager son écran entre 2 machines ? Il existe des logiciels spécialisés comme AnyDesk, mais voyons une façon de faire en Python.

La partie "serveur", celle qui partagera son écran, utilisera le module MSS.
De l'autre côté, un "client" utilisera PyGame pour afficher ce que le serveur lui enverra.


Serveur

Grâce au module MSS, on peut atteindre de belles performances. Couplé à une compression de données suffisante, on énonomise la bande passante. Le code suivant utilise une compression ZLib, mais on pourrait aussi bien laisser sa chance à LZ4 ou un autre algorithme.

import socket
import threading
import zlib

import mss

# Dimensions des captures d'écran, plus petit = plus rapide
WIDTH = 1900
HEIGHT = 1000


def retreive_screenshot(conn):
    """ Envoi des captures d'écran via un socket. """

    # Si utilisation via SSH, il est possible de spécifier le $DISPLAY à utilser :
    # with mss(display=':0.0') as sct:
    with mss.mss() as sct:
        # La région de l'écran à capturer
        rect = {'top': 0, 'left': 0, 'width': WIDTH, 'height': HEIGHT}

        while 'recording':
            # Prendre la capture d'écran
            img = sct.grab(rect)
            # Ajuster le niveau de compression ici (0-9)
            pixels = zlib.compress(img.rgb, 6)

            # Envoie de la taille de la taille des pixels
            size = len(pixels)
            size_len = (size.bit_length() + 7) // 8
            conn.send(bytes([size_len]))

            # Envoie de la taille des pixels
            size_bytes = size.to_bytes(size_len, 'big')
            conn.send(size_bytes)

            # Envoi des pixels compressés
            conn.sendall(pixels)


def main(host='0.0.0.0', port=5000):
    with socket.socket() as sock:
        sock.bind((host, port))
        sock.listen(5)
        print('Server started.')

        while 'connected':
            conn, addr = sock.accept()
            print('Client connected IP:', addr)
            thread = threading.Thread(target=retreive_screenshot, args=(conn,))
            thread.start()


if __name__ == '__main__':
    import argparse
    import sys
    
    cli_args = argparse.ArgumentParser()
    cli_args.add_argument('--port', default=5000, type=int)
    options = cli_args.parse_args(sys.argv[1:])
    
    main(port=options.port)

Client

Son utilisation est on ne peut plus simple : python3 client.py --host=192.168.0.10.

import socket
import zlib

import pygame

# from server import WIDTH, HEIGHT
WIDTH = 1900
HEIGHT = 1000


def recvall(conn, length):
    """ Récupération de tous les pixels. """

    print(length % 1024, 'ko')
    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf


def main(host='127.0.0.1', port=5000):
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()

    with socket.socket() as sock:
        sock.connect((host, port))
        watching = True

        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Récupération de la taille de la taille des pixels, la taille des pixels et les pixels
            size_len = int.from_bytes(sock.recv(1), byteorder='big')
            size = int.from_bytes(sock.recv(size_len), byteorder='big')
            pixels = recvall(sock, size)
            pixels = zlib.decompress(pixels)

            # Création d'une Surface depuis les pixels brutes
            img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

            # Affichage de l'image
            screen.blit(img, (0, 0))
            pygame.display.flip()
            clock.tick(60)


if __name__ == '__main__':
    import argparse
    import sys
    
    cli_args = argparse.ArgumentParser()
    cli_args.add_argument('--host', default='127.0.0.1', type=str)
    cli_args.add_argument('--port', default=5000, type=int)
    options = cli_args.parse_args(sys.argv[1:])
    
    main(host=options.host, port=options.port)