![](/img/trans.png)
[英]python exit infinite while loop with KeyboardInterrupt exception
[英]Exit loop with KeyboardInterrupt then begin another loop in python
我目前有一段代碼旨在通過 TCP 設備服務器與兩個電機通信,該設備服務器向它們發送 ASCII 命令以跟蹤正弦路徑。 我希望讓運動無限期地繼續,然后在觸發KeyboardInterrupt
時立即停止,然后在程序結束之前讓電機回到它們定義的起始位置。
此代碼當前可以復制正弦運動,但當前不會在觸發KeyboardInterrupt
時立即停止,電機也不會返回其原始位置。 正弦循環的設計使得當KeyboardInterrupt
發生時,一個名為move
的全局變量從 True 變為 False,這會中斷循環。 簡化代碼如下:
import socket
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.connect(("192.168.177.200", 4001)) # Y motor
s2.connect(("192.168.177.200", 4002)) # X motor
# Disengage the motor to allow manual movement by wheel
s1.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
homeposition = input("Are the motors centred? Press 'y' to confirm: ")
if homeposition == 'y':
s1.send("EN\n".encode("ASCII"))
s2.send("EN\n".encode("ASCII")) # energise the motors so they cannot be moved
print("Motors Engaged")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
else:
print("Set home position and restart program")
exit()
#----ADD DATA FOR SAMPLING SINUSODIAL FUNCTIONS----
radius = input("Desired radius of movement (mm):")
radius = float(radius)
print("radius of circular path (mm): ", radius)
# need slightly different ratios for each motor due to different thread sizes
gearpositionlim_x = 20000 #one rotation equals 2.5mm (+ bearing ration on manipulator of 2:1)
gearpositionlim_y = 10000 #one rotation equals 2mm
# sample sine and cosine
step = 2*pi / 1000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim_x*np.cos(time_range)
y_motorrange = gearpositionlim_y*np.sin(time_range)
x_motorrange = ['la'+str(int(i)) for i in x_motorrange]
y_motorrange = ['la'+str(int(i)) for i in y_motorrange]
#print(x_motorrange)
x_motorrange_wcom = []
y_motorrange_wcom = []
{x_motorrange_wcom.extend([e, 'm', 'np']) for e in x_motorrange} # add movement prompts and wait for movement to complete
{y_motorrange_wcom.extend([e, 'm', 'np']) for e in y_motorrange} # add movement prompts and wait for movement to complete
# Set Acceleration and Deceleration of Motors
s1.send("AC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("AC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Acceleration set to 10 ")
s1.send("DEC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DEC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Deceleration set to 10")
def setup(): #move to initial position before starting movement
s2.send(str(str(x_motorrange_wcom[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
move = False
print(move)
end()
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
我相信我的問題在於我的 function motormove()
,但我不確定我應該做什么才能實現我想要的操作。 有誰知道如何做到這一點?
提前致謝
使用庫信號應該足以滿足您的用例。 請參見下面的代碼。
import socket
import signal
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
gearpositionlim = int(10000)
# sample sine and cosine
step = 2*pi / 2000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim*np.sin(time_range)
y_motorrange = gearpositionlim*np.cos(time_range)
def handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == 'y':
exit(1)
else:
#Do STH
def setup():
s2.send(y_motorrange[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
signal.signal(signal.SIGINT, handler)
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
這應該工作得很好,注意信號 function 在KeyboardInterrupt上被調用,這重定向到信號 function ,你可以退出或做其他事情。
我會重新安排您的代碼以刪除重復項(請注意,以下內容未經測試,但您應該明白):
from socket import socket, AF_INET, SOCK_STREAM
from time import sleep
import numpy as np
import math
class Motor:
def __init__(self, gearposition_limit=10000, step_count=2000):
self.socket = socket(AF_INET, SOCK_STREAM)
self.step = 2 * math.pi / step_count
self.time_range = np.arange(0, 2 * math.pi + self.step, self.step)
self.x_range = gearposition_limit * np.sin(self.time_range)
self.y_range = gearposition_limit * np.cos(self.time_range)
self.reset()
def send(self, *args):
try:
for c in args:
self.socket.send(f'{c}\n'.encode("ASCII"))
except KeyboardInterrupt:
self.end()
def reset(self):
self.send(self.x_range[0], "m", "np", "delay200", "HO")
def end(self):
self.send("la0", "m", "np", "delay200", "DI", "delay200")
m1 = Motor()
m2 = Motor()
input("Ready. Press enter to proceed")
print("Running. Press CTRL+C to end")
m1.send(*m1.x_range)
sleep(2)
m2.send(*m2.x_range)
如果您想在兩個電機上獨立平行移動,則需要研究多線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.