Importing python files/functions from the same directory (as simple as it sounds!)
Hello everyone,
I've managed to run in an incredible issue that me and my friend just are not able to solve. Luckily, we managed to replicate the issue in the example talker.py
and listener.py
. My issue is that I cannot seem to import any function from another python file, even when these files are located in the same folder as the talker.py
file.
Here is the code (you just need talker.py for this):
#!/usr/bin/env python
import rospy
from sum import Sum
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
print(Sum(1,2))
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
the sum.py:
#!/usr/bin/env python
def Sum(a,b):
return a + b
And what I have added to the CMakeLists.txt file:
catkin_install_python(PROGRAMS
scripts/talker.py scripts/listener.py scripts/sum.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
after doing catkin_make
, source devel/setup.bash
, and rosrun test talker.py
I get the output:
Traceback (most recent call last):
File "/home/-/catkin_ws/devel/lib/test/talker.py", line 15, in <module>
exec(compile(fh.read(), python_script, 'exec'), context)
File "/home/-/catkin_ws/src/test/scripts/talker.py", line 40, in <module>
from sum import Sum
ImportError: cannot import name 'Sum' from 'sum' (/home/-/catkin_ws/devel/lib/test/sum.py)
where test
is the name that I gave the package.
Things I have tried (to no avail):
- add
import rospy
to thesum.py
file - use
catkin build test
instead ofcatkin_make
- use the
setup.py
file - use a blank
__init__.py
file
I'm quite frankly at a loss on what to do. It seems like such a fundamental thing to do, that I'm afraid I'm missing something extremely obvious. However, after a lot of search engine work, it seems that no one has such as simple problem before (most of what I find relates to importing functions/files/modules from different packages etc.)
Any help or hints would be really appreciated!
Cheers!
Asked by none on 2023-01-27 11:59:54 UTC
Answers
In python3, for a ros node consisting of multiple .py files, it looks like there are two approaches you can take:
Path 1. No python module. Do NOT use
catkin_install_python
in the CMakeLists.txt, and set the executable bit on your main .py file. Importing another python file from the same directory will work. The downside of this simple approach is that the ros package can not be installed to /opt/ros/, but it's fine for development purposes.Path 2. Use a python module. Put your .py files in a python module, add a setup.py to top-level to install the python module, and use
catkin_install_python()
andcatkin_python_setup()
in CMakeLists.txt. Your imports must be changed to use the dot-prefix notation (e.g. from .sum import Sum)Do not put a
__init__.py
in your ros package's scripts/ directory. roslaunch and rosrun do not expect to find a python package there.You should not mix the output of
catkin_make
andcatkin build
- they are incompatible. You must use one or the other, and fully remove the directoriescatkin_ws/build/
andcatkin_ws/devel/
if you switch between them.You are asking for trouble using a ros or python package name of "test". It's theoretically legal, but the probability of an undesired name collision is very high.
Asked by Mike Scheutzow on 2023-01-28 10:13:14 UTC
Comments
Hi Mike, I understand that catkin_make
and catkin build
are incompatible, and I have definitely removed the build
and devel
folders between building, yet the issue remains. If I do catkin_make
from scratch, I still get the error you highlighted (and similarly for a clean catkin build
, so I'm not sure how to approach this.
Asked by none on 2023-01-29 09:25:49 UTC
I updated my answer.
Asked by Mike Scheutzow on 2023-01-29 10:16:28 UTC
Thanks Mike!
- in
devel/lib/test/
it does indeed show all three files + an empty cmake.lock file. If I removesum.py
from the CMakeListscatkin_install_python
statement, the respective linker file disappears, yet the error remains... Intuitively, it might have to do with relevant imports that have now disappeared (I'm more amazed by it not working when I do addsum.py
to the CMake file. - Done! yet unfortunately still the same issue.
Regarding 1., it does feel to me that it would have to work without the sum.py
as it would require me to, in the future, include every possible python file to the catkin_install_python
which would get very messy
Asked by none on 2023-01-29 10:31:30 UTC
I appreciate Mike's help. Hopefully, this answer can help someone that stumbles upon the same importing issue.
I'm not quite sure what the underlying problem is, yet allow me to show the structure that removes the error:
CMakeLists.xtx
:
cmake_minimum_required(VERSION 3.0.2)
project(test_package)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
message_generation
rospy
std_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES test
# CATKIN_DEPENDS rospy std_msgs message_runtime
# DEPENDS system_lib
)
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
catkin_install_python(PROGRAMS
src/talker.py
src/listener.py #src/test_package/sum.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
package.xml
<?xml version="1.0"?>
<package format="2">
<name>test_package</name>
<version>0.0.0</version>
<description>The test package</description>
<maintainer email="anon@todo.todo">anon</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>message_generation</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<export>
</export>
</package>
setup.py
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# fetch values from package.xml
setup_args = generate_distutils_setup(
packages=['test_package'],
package_dir={'': 'src'},
)
setup(**setup_args)
talker.py
#!/usr/bin/env python
import rospy
from test_package.sum import Sum
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
print(Sum(1,2))
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
And most importantly, the file structure:
catkin_ws/src/test_package
/src
/test_package
__init__.py
sum.py
talker.py
listener.py
CmakeLists.txt
package.xml
setup.py
where I build with catkin build
, then source devel/setup.bash
and rosrun test_package talker.py
after running an instance of roscore
. Given the location of the __init__.py
and the setup.py
file, I suspect something went wrong there initially.
Asked by none on 2023-01-31 04:54:30 UTC
Comments