Python Forum
I try to import Vpython and I get a "ZeroDivisionError"
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
I try to import Vpython and I get a "ZeroDivisionError"
#1
I'm new on Python, maybe my question is simple.
I want to simulate some physical situations. I learned that Vpython makes it easy to create simple visualizations, allowing programmers to focus more on the computational aspect of their programs. So I want to learn Vpython.
But I get a "ZeroDivisionError" Exception when I try to import vpython(the module I used is 7.6.4).
Error:
Exception ignored in atexit callback: <function Exit at 0x00000212BA80B420> Traceback (most recent call last): File "D:\pythonProject\OpenCVLearning\venv\Lib\site-packages\vpython\vpython.py", line 22, in Exit a = 1.0/zero ~~~^~~~~ ZeroDivisionError: float division by zero
I find the source code of Vpython and there is a "Exit" function:
def Exit():
    zero = 0.
    print('exit')
    a = 1.0/zero
There is a 1.0/zero, it desn't make any sense. I think it is a very confusing behaviour.
likes this post
Reply
#2
(Jul-23-2023, 02:10 PM)Jon2222 Wrote: There is a 1.0/zero, it desn't make any sense. I think it is a very confusing behaviour.
Commit 5051943 so there they add it,maybe not the best way to solve this.
But it should have no impact on import of vpython library.
Quick test.
(dl_env) G:\div_code\dl_env
λ python
Python 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import vpython
>>>
>>> vpython.version
['7.6.4', 'jupyter']
>>> vpython.box()
<vpython.vpython.box object at 0x000001C70A3BB610>
>>> vpython.cylinder()
<vpython.vpython.cylinder object at 0x000001C721AC3640>
>>>
likes this post
Reply
#3
(Jul-23-2023, 07:24 PM)snippsat Wrote: But it should have no impact on import of vpython library.
I use PyCharm and the IDE raises exception even if there is just one line of code to import vpython.
from vpython import *
   
likes this post
Reply
#4
I suggest a dirty trick:
import atexit
_register, atexit.register = atexit.register, (lambda func, *args, **kwargs: func)
try:
    from vpython import *
finally:
    atexit.register = _register
    del _register
Jon2222 likes this post
Reply
#5
(Jul-24-2023, 10:05 AM)Gribouillis Wrote: I suggest a dirty trick:
import atexit
_register, atexit.register = atexit.register, (lambda func, *args, **kwargs: func)
try:
    from vpython import *
finally:
    atexit.register = _register
    del _register

It worked!!! Big Grin
But I don't understand why did you modify a function to be executed at termination?
I find out the source code of function register:
def register(func, *args, **kwargs): # real signature unknown; restored from __doc__
    """
    register(func, *args, **kwargs) -> func
    
    Register a function to be executed upon normal program termination
    
        func - function to be called at exit
        args - optional arguments to pass to func
        kwargs - optional keyword arguments to pass to func
    
        func is returned to facilitate usage as a decorator.
    """
    pass
I still have two problems even if I successfully imported Vpython with your suggestion.
  1. This function doesn't seem to do anything, why does it not report the error after modifying this function?
  2. I would like to know if this is a good way to shoot this kind of trouble.
  3. I think this piece of code can add a atexit.register run in the termination to avoid the execution of the Exit function in vpython. I don't know if my opinion is right.

Reply
#6
(Jul-24-2023, 12:54 PM)Jon2222 Wrote: I find out the source code of function register:
This is not the actual code of function register. For CPython, the actual code is written in C in file atexitmodule.c (see the C function atexit_register() in this file). So I actually replaced a function that does something by a function that does nothing.

We could replace by a function that targets more precisely the problem, for example
import atexit
import functools
import contextlib

def register():
    _atexit_register = atexit.register
    
    def register(func, *args, **kwargs):
        if getattr(func, '__name__', '') == 'Exit':
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                with contextlib.suppress(ZeroDivisionError):
                    return func(*args, **kwargs)
            _atexit_register(wrapper, *args, **kwargs)
        else:
            _atexit_register(func, *args, **kwargs)
        return func
    register.old = _atexit_register
    return register
    
register = register()
atexit.register = register
try:
    from vpython import *
finally:
    atexit.register = register.old
    del register
Jon2222 likes this post
Reply
#7
@snippsat is correct. You do not get the error when importing the library. It only has an effect when the program exits, which happens immediately if your program consists solely of "import vpython". Try this:
import vpython
import time

time.sleep(10)
No error until 10 seconds has passed.

My guess is the divide by zero function is a default exit function that you are meant to override.
Reply
#8
(Jul-24-2023, 02:10 PM)deanhystad Wrote: My guess is the divide by zero function is a default exit function that you are meant to override.
Isnt'it too late to override it after it has been registered by atexit, which seems to happen when the module is imported?

In all cases, it should be documented somewhere. It looks so ridiculous a "feature".
Reply
#9
Also found this in the documentation.
Quote:When running from a terminal, if the program does not end with a loop
containing a rate() statement, you need to add "while True: rate(30)"
to the end of the program. This is not necessary when launching from
environments such as Jupyter notebook, IDLE, or Spyder.
Reply
#10
(Jul-24-2023, 01:54 PM)Gribouillis Wrote:
(Jul-24-2023, 12:54 PM)Jon2222 Wrote: I find out the source code of function register:
This is not the actual code of function register. For CPython, the actual code is written in C in file atexitmodule.c (see the C function atexit_register() in this file). So I actually replaced a function that does something by a function that does nothing.

We could replace by a function that targets more precisely the problem, for example
import atexit
import functools
import contextlib

def register():
    _atexit_register = atexit.register
    
    def register(func, *args, **kwargs):
        if func.__name__ == 'Exit':
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                with contextlib.suppress(ZeroDivisionError):
                    return func(*args, **kwargs)
            _atexit_register(wrapper, *args, **kwargs)
        else:
            _atexit_register(func, *args, **kwargs)
        return func
    register.old = _atexit_register
    return register
    
register = register()
atexit.register = register
try:
    from vpython import *
finally:
    atexit.register = register.old
    del register


I understand this, thank you.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  ZeroDivisionError laurawoods 1 215 Apr-11-2024, 03:27 AM
Last Post: deanhystad
  Overcoming ZeroDivisionError: division by zero Error dgrunwal 8 5,060 Jun-12-2020, 01:52 PM
Last Post: dgrunwal
  ZeroDivisionError CIVILmath 2 2,524 Jan-17-2019, 02:38 AM
Last Post: CIVILmath
  Vpython Delay in plotting points SohaibAJ 0 2,073 Jul-30-2018, 08:44 PM
Last Post: SohaibAJ
  Anaconda / Spyder / VPython mwatson87 3 90,423 May-24-2018, 01:51 PM
Last Post: snippsat
  VPython - Trying to make orbit simulation totalnoob 2 5,637 Sep-13-2017, 03:59 PM
Last Post: micseydel

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020