Jack_Hu
Jack_Hu

Reputation: 1379

PyCharm - from turtle import * -- Giving unused import reference

PyCharm isn't importing/resolving properly. The code runs okay, but it isn't getting code completion, and is flagging up as errors (red squiggly lines).

The code that demonstrates this is as follows:

from turtle import *

forward(40)
right(45)
forward(80)


import turtle

t = turtle.Turtle()

t.forward(40)
t.right(45)
t.forward(80)

And a picture that demonstrates the issue in PyCharm:

https://prnt.sc/ni9dvk

Does anyone have any ideas on how to solve this problem? It's pretty annoying to not be able to use from X import Y.

Upvotes: 0

Views: 1709

Answers (3)

cdlane
cdlane

Reputation: 41872

What's going on here is that Python turtle is unusual in that it has two different interfaces, a functional one and an object-oriented one. If you use the object-oriented one, everything should work fine:

from turtle import Screen, Turtle

yertle = Turtle()

yertle.forward(40)
yertle.right(45)
yertle.forward(80)

screen = Screen()

screen.exitonclick()

The functional interface is there to make things easier for beginners:

from turtle import *

forward(40)
right(45)
forward(80)

exitonclick()

or:

import turtle

turtle.forward(40)
turtle.right(45)
turtle.forward(80)

turtle.exitonclick()

But you shouldn't mix the two! As that is a primary source of turtle confusion.

The issue with PyCharm is that the turtle functional API is derived from the object-oriented API at load time, so it's not there for PyCharm to find when it scans the source file. The turtle methods are all mapped onto the default turtle and screen methods are all mapped onto the singular screen instance.

Upvotes: 0

DeepSpace
DeepSpace

Reputation: 81614

As a rule of thumb, do not use from X import *, regardless of what package X is or what its documentation says, It will only lead to bugs later down the road.

Why "star imports" should be avoided

from turtle import *

def forward():
    print('forward')

forward(45)

What do you think will happen?

turtle.forward is overwritten by the locally defined forward function, and we will get an error TypeError: forward() takes 0 positional arguments but 1 was given

Why it works in this case

from turtle import *

forward(40)

To understand why the above works even though Pycharm says that forward is not defined we have to see how the turtle module is implemented, and then understand how Python imports work and how Pycharm checks for "definitions" of used names.

turtle.py

tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
               'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
_tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
        'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
        'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
        'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
        'register_shape', 'resetscreen', 'screensize', 'setup',
        'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
        'window_height', 'window_width']
_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
        'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
        'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
        'fillcolor', 'filling', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
        'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
        'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
        'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
        'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
        'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
        'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
        'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
        'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
        'write', 'xcor', 'ycor']
_tg_utilities = ['write_docstringdict', 'done']

__all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
           _tg_utilities + ['Terminator'])  

...

As you can see, it simply prepares some lists of strings (which are names of functions/classes/etc) then concats everything to a single list and assigns everything to the __all__ global variable.

I will not go into much details about __all__ (since there are several Q&A on SO on that topic, for example Can someone explain __all__ in Python?), but basically it tells the interpreter what names should be available when doing from X import *.

When you are doing from turtle import * then using forward, right etc, they are available to use since their name is inside __all__, but Pycharm has no idea that they will be exposed by __all__ at runtime.

Upvotes: 2

a-8k
a-8k

Reputation: 1

Try this:

from turtle import Turtle

it must work.

greetings.

Upvotes: -1

Related Questions