"import easygopigo3" vs "from easygopigo3 import EasyGoPiGo3"

Greetings!

Ref:

Issue:
I am experimenting with the EasyGoPiGo3/easygopigo3 libraries using Thonny and the Python “command line”

On the documentation web-site,
(https://gopigo3.readthedocs.io/en/master/api-basic/structure.html)

it says

 
If I execute “import easygopygo3” as the documentation suggests, it succeeds.  (i.e. It returns the “>>>” prompt.)

Then if I try to instantiate the EasyGoPiGo3 class by executing “Charlie = EasyGoPiGo3()”, it throws an error that “EasyGoPiGo3” doesn’t exist/is undefined, or something similar.

In contrast, if I execute “from easygopigo3 import EasyGoPiGo3” then try to instantiate the class, it succeeds.

Confusion reigns supreme.

My understanding of the “import” statement was that if I didn’t import something explicitly from a library, it imported everything.

Viz.:

  • “import easygopigo3” = “from easygopigo3 import *” (Which includes  EasyGoPiGo3 - along with whatever else is there.)
  • Whereas “from easygopigo3 import EasyGoPiGo3” imports ONLY  the EasyGoPiGo3 part of the library, excluding everything else.

 
Obviously my understanding is not correct since trying to access the module/method “EasyGoPiGo3” when importing using the first statement results in ignominious failure, shame, humiliation, and a decided lack of cooperation from the robot.

  1. Why does the documentation recommend the first style of import if it doesn’t work?
  2. Why doesn’t it work?
  3. If it should  work, what am I doing wrong?

Thanks!

import easygopigo3

egpg = easygopigo3.EasyGoPiGo3()

----

from easygopigo3 import EasyGoPiGo3

egpg = EasyGoPiGo3()

The first makes every use of the content explicitly say where it comes from.

The second actually hides where the class comes from, so can cause extra work to find where the specification is located when there are lots of imports of classes that are not obvious from a module - (e.g. I will gather non-class utility functions and related classes in one module - probably not to style guidelines)

PEP-0008 “Imports”:

1 Like

This has to do with namespaces. When you use import easygopigo3 everything gets imported but kept in the easygopigo3 namespace, which forces you to use easygopigo3.EasyGoPiGo3()

If you use from easygopigo3 import * you are saying to take everything inside easygopigo3 and bring it directly into the main namespace.

If you use from easygopigo3 import EasyGoPiGo3 you are saying to take just the EasyGoPiGo3 class from the library which, in our case, means everything because there’s only that one class in the library.

Does this help?

2 Likes

Actually his problem is that the DI readthedocs says “import easygopigo3” but then gives example code that needs “from import easygopigo3 import EasyGoPiGo3”

# we need an EasyGoPiGo3 object for instantiating sensor / actuator objects
gpg3_obj = EasyGoPiGo3()
1 Like

Ah, indeed. Fix now upcoming in documentation. This takes a bit longer than a code fix but it should be done in the next 24 hours.

2 Likes

Absolutely!

One of those things that is “so obvious” that people forget to mention it to those of us who are still in (ahem!) “ground-school” so to speak.

Makes total sense.

Might I have usage examples of these two cases?

I believe that the second of these would be something like:
servo1=EasyGoPiGo.init_servo(“SERVO1”)

Therefore, the first of these two would be:
servo1=init_servo(“SERVO1”)?

Isn’t that like importing all the class methods without the class itself?  Correct me if I’m wrong, but isn’t that a software bug waiting to happen?  My understanding of classes was that a class was (sort-of like) a “wrapper” for the classes methods to encapsulate them, right?

Example: (psudo-code)
Class1
Method1 ==> “rotate_servo(parameters)” that moves one of the two servos on the 'bot

Class2
Method1 ==> “rotate_servo(parameters)” that is responsible for controlling the “servos” (motors with built-in rotary encoders) that control the wheels.

Without the class “wrappers” - this is a train-wreck waiting to happen.  Right?