I'm following a tutorial on understanding writing python publisher in ROS2. This is an example that I'm creating. The code does not seem to have any errors but in vscode, the self word is underlined in red and when I hover the mouse it shows that "self" is not defined. How can I resolve this issue in vscode?
I will add the code here
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.msg import String
class RobotNewsStationNode(Node): #modify name
def __init__(self):
super().__init__("robot_news_station") #modify name
self.publisher_ = self.create_publisher(String, "robot_news", 10)
def publish_news(self):
msg = String()
msg.data = "Hello"
self.publisher_.publish(msg)
def main(args=None):
rclpy.init(args=args)
node = RobotNewsStationNode() #modify name
rclpy.spin(node)
rclpy.shutdown()
if __name__ == "__main__":
main()
This is the code error im having in vscode
As the error mentions, you are most likely mixing spaces/tabs.
Try delete all indentation untill that line, then use "tab" to indent your code, and be consistent about it i.e dont mix tabs and space.
Related
I use the excellent Python Click library for handling command line options in my tool. Here's a simplified version of my code (full script here):
#click.command(
context_settings = dict( help_option_names = ['-h', '--help'] )
)
#click.argument('analysis_dir',
type = click.Path(exists=True),
nargs = -1,
required = True,
metavar = "<analysis directory>"
)
def mytool(analysis_dir):
""" Do stuff """
if __name__ == "__main__":
mytool()
If someone runs the command without any flags, they get the default click error message:
$ mytool
Usage: mytool [OPTIONS] <analysis directory>
Error: Missing argument "analysis_dir".
This is nice, but I'd quite like to tell (very) novice users that more help is available by using the help flag. In other words, add a custom sentence to the error message when the command is invalid telling people to try mytool --help for more information.
Is there an easy way to do this? I know I could remove the required attribute and handle this logic in the main function, but that feels kind of hacky for such a minor addition.
Message construction for most errors in python-click is handled by the show method of the UsageError class: click.exceptions.UsageError.show.
So, if you redefine this method, you will be able to create your own customized error message. Below is an example of a customization which appends the help menu to any error message which answers this SO question:
def modify_usage_error(main_command):
'''
a method to append the help menu to an usage error
:param main_command: top-level group or command object constructed by click wrapper
:return: None
'''
from click._compat import get_text_stderr
from click.utils import echo
def show(self, file=None):
import sys
if file is None:
file = get_text_stderr()
color = None
if self.ctx is not None:
color = self.ctx.color
echo(self.ctx.get_usage() + '\n', file=file, color=color)
echo('Error: %s\n' % self.format_message(), file=file, color=color)
sys.argv = [sys.argv[0]]
main_command()
click.exceptions.UsageError.show = show
Once you define your main command, you can then run the modifier script:
import click
#click.group()
def cli():
pass
modify_usage_error(cli)
I have not explored whether there are runtime invocations of ClickException other than usage errors. If there are, then you might need to modify your custom error handler to first check that ctx is an attribute before you add the line click.exceptions.ClickException.show = show since it does not appear that ClickException is fed ctx at initialization.
I'm trying to use a dialog box in order to report an error to the user. It seems to be working if there is one error although when there are multiple it doesn't reopen when closed with the next error and instead crashes.
def errordialog(self, errormessage):
self.errordialog = QMessageBox()
self.errordialog.addButton("OK", 0)
self.errordialog.setText(errormessage)
self.errordialog.exec()
And this is the main program
def validate_data(data, regex):
if re.match(regex, data, re.VERBOSE):
error = False
else:
errormessage = "ERROR"
print("0")
self.errordialog(errormessage)
print("1")
self.errordialog.accept() # I added this in while trying to solve the issue
print("2")
error = True
return error
data = supplierid
regex = "[A-Z]$"
error = validate_data(data, regex)
print("3")
data = suppliername
regex = ".(1,50)$"
error = validate_data(data, regex)
print("4")
It prints 0,1,2,3,0 and then crashes
the error message is object QMessageBox is not callable
After calling this line of code self.errordialog(errormessage), you go into the errordialog function. However, inside the errordialog function, you have redefined self.errordialog so that it is of class QMessageBox instead of class function, so when it goes through the validation the second time, you attempt to call the QMessageBox, which does not work.
Simply changing the function or variable names will solve this problem.
In my project i use module from known bt_manager to decode sbc audio stream. This module is python wrap for C-functions from rtpsbc library.
class SBCCodec:
def __init__(self, config):
import sys
try:
self.codec = ffi.verify(b'#include "rtpsbc.h"',
libraries=[b'rtpsbc'],
ext_package=b'rtpsbc')
except:
print 'Exception:', sys.exc_info()[0]
self.config = ffi.new('sbc_t *')
self.ts = ffi.new('unsigned int *', 0)
self.seq_num = ffi.new('unsigned int *', 0)
self._init_sbc_config(config)
self.codec.sbc_init(self.config, 0)
When i try to create SBCCodec class instance it gives me:
AttributeError: SBCCodec instance has no attribute 'codec'
You can see this attribute in the piece of code i posted above. It works with ffi-methods (ffi.verify, ffi.new). When i input those commands in ipython everything works correct without errors.
What have i missed?
As #Torxed has already mentioned the only way this would happen is if ffi.verify inside your try block throws an exception. If that happens self.codec will not be initialised. If that happens your code does not rethrow the exception and continues as normal after simply printing (which is not clean behaviour). The final statement then tries to call self.codec.config.sbc_init, that is it assumes that self.codec is already intialised, which is incorrect in this particular case and that is why you get the AttibuteError.
If you want to create the instance anyway regardless of the failure for ffi.verify at the start of init define self.codec = None and in your final statement insert a check such as:
if (self.codec != None ):
self.codec.sbc_init(self.config, 0)
Hope that helps.
#!/usr/bin/env python2.7
##-*- mode:python;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t;python-indent:2 -*-'
import noesy
import argparse
import library
parser =argparse.ArgumentParser(description="read pdb file",
add_help=True)
parser.add_argument("file",help="protein pdb file")
library.add_standard_args( parser )
args = parser.parse_args()
def read_structure(pdbfile):
struct=[]
for line in pdbfile:
if len(line):
struct.append(PDBAttributes.read_from_line(line))
return struct
pdb=read_structure(open(args.file,'r'))
class PDBAttributes:
def __init__(self, atomindex=1, atom=noesy.Atom(), atomx=1, atomy=1, atomz=1):
self._atomindex=atomindex
self._atom=atom
self._atomx=atomx
self._atomy=atomy
self._atomz=atomz
def __str__(self):
s='ATOM %(_atomindex)d %(_atom)s at %(_atomx)8.3f %(_atomy)8.3f %(_atomz)8.3f'%self.__dict__
return s
def atom(self):
return self._atom
def atomindex(self):
return self._atomindex
def atomx(self):
return self._atomx
def atomy(self):
return self._atomy
def atomz(self):
return self._atomz
#classmethod
def read_from_line(obj,line):
tags=line.split()
atomindex=int(tags[1])
atom=noesy.Atom(tags[2],int(tags[5]))
atomx=float(tags[6])
atomy=float(tags[7])
atomz=float(tags[8])
obj=PDBAttributes(atomindex, atom, atomx, atomy, atomz)
print obj
class AtomDistance(PDBAttributes):
def distance(self, atom1,atom2):
pass
The NameError you are getting is due to the order you have placed the code in your file.
When you call read_structure to create a value for the pdb variable, it tries to look for PDBAttributes, but it has not been defined yet. If you move that line lower down in the file (below the class definition) you'll avoid that error. Note that it is OK to have the declaration of read_structure above the PDBAttributes class definition, though you might want to move it lower too to make the code easier to understand.
Here's a very simple bit of code that demonstrates the same error:
def foo():
print(foo_text)
foo() # raises a NameError
foo_text = "foo"
Here's a fixed version:
def foo():
print(foo_text)
foo_text = "foo"
foo() # no error, prints "foo"
Move your call of read_structure to follow the definition of the PDBAttributes class.
Also, in the process of reformatting your post, I see that you have mixed tabs and spaces for your indentation. Try reformatting your code to use all spaces for indentation, the recommended form is 4-space indents.
Your definition of all those getter functions looks like Java written in Python - this is a lot of extra code that is often unnecessary in Python. The recommended approach is to omit these all-they-do-is-assign-a-value-to-an-attribute-with-the-same-name-but-with-a-leading-underscore methods and just use attributes with the public names. See Python is Not Java.
I have 2 classes. The first is named test and goes as following:
import textbox
class test:
a=textbox("test")
a.run()
the second class is textbox and goes as following:
class textbox():
def __init__(self, string):
self.string=string
def run(self):
print string
i get this error
File "C:\Users\User\Desktop\edoras\gui\test.py", line 4, in test
a=textbox("test")
TypeError: 'module' object is not callable
I use the pydev eclipse plugin
Try
a = textbox.textbox("test")
or alternatively use
from textbox import textbox
Not sure about the error you mention, but your print statement in text box.run is wrong:
print self.string
You are calling directly the module textbox, which is not allowed.
Maybe it contains an omonymous function? In that case you should call
textbox.textbox('test')
(the first textbox would be the module name, and the second a function inside it)