Search code examples
pythonlistenerexit

Python script not stopping on sys.exit()


I wrote a script that can draw polylines (it over on github) from ScalableVectorGraphics(.svg) by moving the Mouse accordingly.

When you are handing the control over your mouse to a script, a killswitch is certainly necessary, so I found an example for a Keyboard listener somwhere on the Internet:

def on_press(key):
try:
    sys.exit()
    print('alphanumeric key {0} pressed'.format(key.char))
    print('adsfadfsa')
except AttributeError:
    print('special key {0} pressed'.format(
        key))

def main():
listener = keyboard.Listener( #TODO fix sys.exit()
    on_press=on_press)
listener.start()

if __name__ == '__main__':
main()

It seems to be working: If i add a a print statement before the sys.exit() it is instantly executed properly. But with sys.exit() it keeps moving my mouse and the python interpreter is still on Taskmanager. I don't know why it keeps executing.

Thank you in advance for your suggestions. MrSmoer

Solution was: os._exit(1)

Full Sourcecode:

from pynput import mouse as ms
from pynput import keyboard
from pynput.mouse import Button, Controller
import threading
import time
from xml.dom import minidom
import re

sys.path.append('/Users/MrSmoer/Desktop/linedraw-master')

mouse = ms.Controller()
tlc = None
brc = None
brc_available = threading.Event()

biggestY = 0
biggestX = 0

drwblCnvsX = 0
drwblCnvsY = 0


def on_click(x, y, button, pressed):
    if not pressed:
        # Stop listener
        return False


def on_press(key):
    try:
        sys.exit()
        print('alphanumeric key {0} pressed'.format(key.char))
        print('adsfadfsa')
    except AttributeError:
        print('special key {0} pressed'.format(
            key))


def initialize():
    print("Please select your programm and then click at the two corners of the canvas. Press any key to cancel.")
    with ms.Listener(
            on_click=on_click) as listener:
        listener.join()

    print('please middleclick, when you are on top left corner of canvas')
    with ms.Listener(
            on_click=on_click) as listener:
        listener.join()

    global tlc
    tlc = mouse.position

    print('please middleclick, when you are on bottom left corner of canvas')
    with ms.Listener(
            on_click=on_click) as listener:
        listener.join()
    global brc
    brc = mouse.position
    mouse.position = tlc
    print('thread finished')
    brc_available.set()


def getDrawabableCanvasSize(polylines):
    global biggestX
    global biggestY

    for i in range(len(polylines)):  # goes throug all polylines
        points = hyphen_split(polylines[i])  # Splits polylines to individual points
        for c in range(len(points)):  # goes throug all points on polyline
            cord = points[c].split(',')  # splits points in x and y axis
            if float(cord[0]) > (biggestX - 5):
                biggestX = float(cord[0]) + 5
            if float(cord[1]) > (biggestY - 5):
                biggestY = float(cord[1]) + 5
    print('TLC: ', tlc)
    print('bigX: ', biggestX)
    print('bigY: ', biggestY)

    cnvswidth = tuple(map(lambda i, j: i - j, brc, tlc))[0]
    cnvsheight = tuple(map(lambda i, j: i - j, brc, tlc))[1]
    cnvsapr = cnvswidth / cnvsheight
    print('Canvasaspr: ', cnvsapr)
    drwblcnvaspr = biggestX / biggestY
    print('drwnble aspr: ', drwblcnvaspr)

    if drwblcnvaspr < cnvsapr:  # es mus h vertikal saugend
        print('es mus h vertikal saugend')
        finalheight = cnvsheight
        finalwidth = finalheight * drwblcnvaspr

    else:  # es muss horizontal saugend, oder aspect ratio ist eh gleich
        print('es muss horizontal saugend, oder aspect ratio ist eh gleich')
        finalwidth = cnvswidth
    scalefactor = finalwidth / biggestX
    print(scalefactor)
    return scalefactor


def drawPolyline(polyline, scalefactor):
    points = hyphen_split(polyline)
    #print(points)
    beginpoint = tlc
    for c in range(len(points)):  # goes throug all points on polyline
        beginpoint = formatPoint(points[c], scalefactor)
        if len(points) > c + 1:
            destpoint = formatPoint(points[c + 1], scalefactor)
            mouse.position = beginpoint
            time.sleep(0.001)
            mouse.press(Button.left)
            # time.sleep(0.01)
            mouse.position = destpoint
            # time.sleep(0.01)
            mouse.release(Button.left)
        else:
            destpoint = tlc
            #print("finished line")
    mouse.release(Button.left)


def formatPoint(p, scale):
    strcord = p.split(',')
    #print(scale)
    #print(tlc)
    x = float(strcord[0]) * scale + tlc[0]  # + drwblCnvsX/2
    y = float(strcord[1]) * scale + tlc[1]  # + drwblCnvsY/2
    #print('x: ', x)
    #print('y: ', y)
    thistuple = (int(x), int(y))
    return thistuple


def hyphen_split(a):
    return re.findall("[^,]+\,[^,]+", a)
    # ['id|tag1', 'id|tag2', 'id|tag3', 'id|tag4']


def main():
    listener = keyboard.Listener( #TODO fix sys.exit()
        on_press=on_press)
    listener.start()

    thread = threading.Thread(target=initialize()) #waits for initializing function (two dots)
    thread.start()
    brc_available.wait()

   # print(sys.argv[1])
    doc = minidom.parse('/Users/MrSmoer/Desktop/linedraw-master/output/out.svg')  # parseString also exists
    try:
        if sys.argv[1] == '-ip':
            doc = minidom.parse(sys.argv[2])
    except IndexError:
        print('Somethings incorrect1')

    polylines = NotImplemented

    try:
        doc = minidom.parse('/Users/MrSmoer/Desktop/linedraw-master/output/out.svg')  # parseString also exists
        # /Users/MrSmoer/Desktop/linedraw-master/output/output2.svg
        #doc = minidom.parse('/Users/MrSmoer/Desktop/Test.svg')
        polylines = [path.getAttribute('points') for path
                     in doc.getElementsByTagName('polyline')]
        doc.unlink()
    except:
        print('Somethings incorrect3')

    # print(polylines)

    scalefactor = getDrawabableCanvasSize(polylines)

    for i in range(len(polylines)):
        drawPolyline(polylines[i], scalefactor)


if __name__ == '__main__':
    main()

Solution

  • Sometimes, when writing a multithreadded app, raise SystemExit and sys.exit() both kills only the running thread. On the other hand, os._exit() exits the whole process.

    While you should generally prefer sys.exit because it is more "friendly" to other code, all it actually does is raise an exception.

    If you are sure that you need to exit a process immediately, and you might be inside of some exception handler which would catch SystemExit, there is another function - os._exit - which terminates immediately at the C level and does not perform any of the normal tear-down of the interpreter

    A simple way to terminate a Python script early is to use the built-in quit() function. There is no need to import any library, and it is efficient and simple.

    Example:

           #do stuff
         if this == that:
          quit()
    

    You may try these options!! Hope it works fine!! If not tell us, we will try more solutions!