I have a publisher that sends a number from 0 to 6, or None. So I convert it to a string before sending it to make sure it can send the "None" value.
self.pub = rospy.Publisher("jugada", String, queue_size=1)
self.pub.publish(str(col))
and then i want the subscriber to receive it:
class clicker(object):
def __init__(self):
self.jugada_sub = rospy.Subscriber("jugada",String, self.callback)
def callback(self, data):
jugada = data
print(jugada)
and instead of printing:
3
instead it prints
Data: "3"
which breaks up the rest of the code I need that number (or None) for.
I tried to str(data) and then try to edit the string to remove the 'Data:' part, but that doesn't work.
I tried to google it for like an hour, but can't figure out how to get rid of the "Data:" or how to change the message type to send only the string.
PS Later in the code i do:
if jugada != "None":
jugada = int(jugada)
and I get the error: int() argument must be a string
and if i do jugada = str(data) at the beginning, i get the error: Invalid literal for int() with base 10: 'data: "3"'
ROS messages are defined as classes, not built in types. For std_msg types you need to retrieve the data directly using the .data attribute. Take the following example:
def callback(self, data):
jugada = data.data
print(jugada)
Another couple of notes. When publishing data it is usually a best practice to not pass the raw type directly to .publish and instead use a message type as follows:
output_msg = String()
output_msg.data = 'some string val'
pub.publish(output_msg)
Lastly, if you're publishing integer data you should use one of the integer types: Int8, Int16, Int32, etc
Related
I am trying to pass number (get_repo_id) to another function and print it but it does not work.
user_name is just string used for selecting from database.
Function that returns get_repo_id:
def selectRepoId(user_name):
local_session = Session(bind=engine)
get_repo_id = local_session.execute(select(User.repo_id).where(User.username == user_name)).first()
local_session.commit()
return get_repo_id
Here i am trying to convert returned value from database to integer.
Functions which prints get_repo_id:
def createEmptyDir(user_name):
user_name = user_name
id_int = selectRepoId(user_name)
id = int(id_int)
print(id)
Error message: TypeError: int() argument must be a string, a bytes-like object or a real number, not 'Row'
I'm doing a project that is requiring a lot of input validation. I currently have a function defined as follows:
def get_valid_float(inputMessage,errorMessage):
while True:
variableInput = input(inputMessage)
try:
variableInput = float(variableInput)
return variableInput
except ValueError:
print(errorMessage)
This function allows me to choose a custom message to prompt the user. It will then validate that the user input is indeed a float, and will print a custom error message in the event that it is not. It will loop until the user gives a valid input.
However, I would rather not create a function to validate each and every data type. It seems like it would be best to combine these into one get_valid_input() function, and pass a third argument allowing me to choose what data type I am attempting to verify. For example, get_valid_input(complex,inputMessage,errorMessage).
I am obviously unable to pass a keyword as an argument. This makes me think the only way to do this would to be to do something like this:
def get_valid_float(dataType,inputMessage,errorMessage):
if dataType == "float"
while True:
variableInput = input(inputMessage)
try:
variableInput = float(variableInput)
return variableInput
except ValueError:
print(errorMessage)
elif dataType == "integer"
while True:
variableInput = input(inputMessage)
try:
variableInput = int(variableInput)
return variableInput
except ValueError:
print(errorMessage)
And so on, with an elif for every data type. Surely there is an easier way to do this, that somehow allows me to execute the line variableInput = {dataType}(variableInput) to confirm that they input a value of data type "dataType". Any ideas?
Just pass as an argument the actual data type, rather than the name of the data type. E.g:
def get_valid_input(dataType, inputMessage, errorMessage):
while True:
value = input(inputMessage)
try:
value = dataType(value)
break
except ValueError:
print(errorMessage)
You would call it like this:
floatvalue = get_valid_input(float, "enter a float value: ", "that is an invalid float")
intvalue = get_valid_input(int, "enter an integer value: ", "that is an invalid integer")
I am obviously unable to pass a keyword as an argument.
Not sure why you're saying that, but you can! :)
Also no need for error message, just catch all Exceptions (Not recommended but since you are just printing out the error it seems fine here)
The message strings aren't really needed, try using the name of the dataType and the exception's message like this:
def get_valid_data(dataType):
while True:
variableInput = input(f"Put in data of type {dataType.__name__}: ")
try:
variableInput = dataType(variableInput)
return variableInput
except Exception as e:
print(e)
get_valid_data(int)
>>> Put in data of type int: "hi"
>>> invalid literal for int() with base 10: '"hi"'
I want to create unit test for a Python 3 method that reads unicode text strings from a serial port. I want to test the method's response to various strings. The line of code that I want to emulate is:
comm_buffer = serial_port.readline().decode("utf-8").strip()
Where 'serial_port' is an instance of a serial port that is passed to the method. I would like to use the unittest.mock module to set the comm_buffer variable to a unicode string, but I have been struggling all day with no success. My first time with trying to use mock, and I'm out of my depth.
The code for the whole method is:
def wait_for_data(serial_port, comm_flag = ""):
"""Read lines of data from the serial_port
Receives optional comm_flag (single character to check for at beginning of string)"""
logging.debug("Start wait_for_data " + comm_flag)
timeout_count = 0
while True:
# Get a line from the buffer and convert to string and strip line feed
logging.debug("Waiting for data…")
comm_buffer = serial_port.readline().decode("utf-8").strip()
if len(comm_buffer) == 0:
timeout_count += 1
logging.warning("Serial port timeout - no data received. Timeout count = " + str(timeout_count))
if timeout_count > 10:
raise TimeoutError(["Too many timeouts"])
# If no id character was specified, just return the string
elif comm_flag == "":
logging.debug("Returning no comm_flag")
return comm_buffer
# If an id character was specified, return the string if it's present (strip id), otherwise wait for another string
elif comm_buffer[0] == comm_flag:
logging.debug("Returning with comm_flag")
return comm_buffer[1:]
Serial_port is not an instance of a serial port but an object with a readline() method. So don’t care about such thing as a serial port, your mock object is an object with the readline() method which provides the kind of value you want to test.
So you just have to crate something like :
port = Mock()
port.readline = Mock(return_value="my string")
This is the first parameter for your call.
So, if I copy your function in a module named test.port this tests are ok :
class TestWaitData(unittest.TestCase):
def testFunc(self):
port = mock.Mock()
port.readline = mock.Mock(return_value="my string".encode('utf-8')) # as you use a decode call
self.assertEqual(test.port.wait_for_data(port), "my string")
def testBufferEmpty(self):
port = mock.Mock()
port.readline = mock.Mock(return_value="".encode('utf-8'))
with self.assertRaises(TimeoutError):
test.port.wait_for_data(port)
def testWithFlag(self):
port = mock.Mock()
port.readline = mock.Mock(return_value="fmy string".encode('utf-8'))
self.assertEqual(test.port.wait_for_data(port, 'f'), "my string")
I am beginning to learn about Session Objects and I have come across an issue which I am sure is very simple.
I thought the idea of a session object was to store a variable so that it could be accessed later? In the below abated piece of code the first print statement works as expected printing "This is self request 2" but the second causes this error:
Exception Type: KeyError
Exception Value: 0
Exception Location: /Library/Python/2.7/site-packages/django/contrib/sessions/backends/base.py
in getitem, line 47
Why is the second print statement not working? Why can I not access self.request.session[0] on the second step of my form?
Any help/tips are much appreciated
Thanks
Code
class SurveyWizardOne(SessionWizardView):
def get_context_data(self, form, **kwargs):
context = super(SurveyWizardOne, self).get_context_data(form, **kwargs)
if self.steps.current in ['5','6','7','8','9']:
step = int(self.steps.current)
if step in (5, 6, 7):
self.request.session[0] = 2
print 'This is self request', self.request.session[0]
elif step == 8:
print 'This is STILL self request', self.request.session[0]
return context
Try to use keys to store values:
request.session['fav_color'] = 'red' #Set the value
fav_color = request.session.get('fav_color', 'red') #Read the value else read a default one
From Django Doc: A wrapper around the JSON serializer from django.core.signing. Can only serialize basic data types.
In addition, as JSON supports only string keys, note that using non-string keys in request.session won’t work as expected
I am trying to use pickle to encode instances of a class and send it across a socket and decode it at the other end, however upon reaching the other end AttributeError: 'module' object has no attribute '' is thrown when calling pickle.loads(). after googling around I confirmed that pickle is correctly importing the module containing the class definition.I cannot figure out why it is looking for a attribute that does not have a name
the function for receiving the packet
def run(self):
while self.alive.isSet():
try:
cmd = self.cmd_q.get(True, 0.1)
self.log.debug('Q Returned')
self.handlers[cmd.type](cmd)
except Queue.Empty as e:
#self.log.debug('Q Returned Empty')
pass
if self.connected.isSet():
self.log.debug('checking packets')
if self.conn:
x = select.select((self.conn,),(),(), 0.1)
self.log.debug('SERVER returned')
else:
x = select.select((self.sock,),(),(), 0.1)
self.log.debug('CLIENT returned')
if len(x[0]) != 0:
self.log.debug('Got Packet')
packet = x[0][0].makefile('rwb').readline()
self.__reply_receive(packet)
the function for sending
def __handle_send(self, cmd):
self.log.debug('Sending.....')
if self.connected.isSet():
packet = pickle.dumps(cmd.data,pickle.HIGHEST_PROTOCOL)
if self.conn:
self.conn.send(packet + '\n')
else:
self.sock.send(packet + '\n')
self.log.debug('Sent!')
and the class definition
class Packet(object):
"""
LINEUP (line)
UPDATE (dict)
INPUT (line)
DISCONN None
TEST (line)
"""
LINEUP, UPDATE, INPUT, DISCONN, TEST = range(5)
def __init__(self, type, data = 'blarg'):
self.type = type
self.data = data
I don't think you can rely on the result of pickle.dumps to not contain any newlines. You'll need another way to find out where the pickled object ends. You might do this by sending the length first. (pickle.load can determine where the object ends, but it would have to block until the whole object can be read.)
Your use of the socket.send method is incorrect. It can send fewer bytes than you request, and it will return the number of bytes sent. You need to make a loop to send the remaining bytes, something like this:
def send_all(sock, string):
bytes_sent = 0
while bytes_sent < len(string):
bytes_sent += sock.send(string[bytes_sent:])
Keep in mind that this will block until all bytes can be sent. If you don't want that, you'll have to integrate this into a select loop.
Printing a hash of your data would probably be a useful test, to figure out whether the error is in transmitting the data or in pickling/unpickling it.