Error in atexit run exitfuncs python

I am trying to run a simple multiple processes application in Python. The main thread spawns 1 to N processes and waits until they all done processing. The processes each run an infinite loop, so t...

I am trying to run a simple multiple processes application in Python. The main thread spawns 1 to N processes and waits until they all done processing. The processes each run an infinite loop, so they can potentially run forever without some user interruption, so I put in some code to handle a KeyboardInterrupt:

#!/usr/bin/env python
import sys
import time
from multiprocessing import Process

def main():
    # Set up inputs..

    # Spawn processes
    Proc( 1).start()
    Proc( 2).start()

class Proc ( Process ):
    def __init__ ( self, procNum):
        self.id = procNum
        Process.__init__(self)

    def run ( self ):
        doneWork = False

        while True:

            try:
                # Do work...
                time.sleep(1)
                sys.stdout.write('.')

                if doneWork:
                    print "PROC#" + str(self.id) + " Done."
                    break

            except KeyboardInterrupt:
                print "User aborted."
                sys.exit()

# Main Entry
if __name__=="__main__":
    main()

The problem is that when using CTRL-C to exit, I get an additional error even though the processes seem to exit immediately:

......User aborted.
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "C:Python26libatexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:Python26libmultiprocessingutil.py", line 281, in _exit_function
    p.join()
  File "C:Python26libmultiprocessingprocess.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:Python26libmultiprocessingforking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt
Error in sys.exitfunc:
Traceback (most recent call last):
  File "C:Python26libatexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:Python26libmultiprocessingutil.py", line 281, in _exit_function
    p.join()
  File "C:Python26libmultiprocessingprocess.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:Python26libmultiprocessingforking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt

I am running Python 2.6 on Windows. If there is a better way to handle multiprocessing in Python, please let me know.

Purpose: Register function(s) to be called when a program is closing down.
Available In: 2.1.3 and later

The atexit module provides a simple interface to register functions to be
called when a program closes down normally. The sys module also provides a
hook, sys.exitfunc, but only one function can be registered there. The atexit
registry can be used by multiple modules and libraries simultaneously.

Examples¶

A simple example of registering a function via atexit.register() looks like:

import atexit

def all_done():
    print 'all_done()'

print 'Registering'
atexit.register(all_done)
print 'Registered'

Since the program doesn’t do anything else, all_done() is called right away:

$ python atexit_simple.py

Registering
Registered
all_done()

It is also possible to register more than one function, and to pass arguments.
That can be useful to cleanly disconnect from databases, remove temporary
files, etc. Since it is possible to pass arguments to the registered
functions, we don’t even need to keep a separate list of things to clean up –
we can just register a clean up function more than once.

import atexit

def my_cleanup(name):
    print 'my_cleanup(%s)' % name

atexit.register(my_cleanup, 'first')
atexit.register(my_cleanup, 'second')
atexit.register(my_cleanup, 'third')

Notice that order in which the exit functions are called is the reverse of
the order they are registered. This allows modules to be cleaned up in the
reverse order from which they are imported (and therefore register their
atexit functions), which should reduce dependency conflicts.

$ python atexit_multiple.py

my_cleanup(third)
my_cleanup(second)
my_cleanup(first)

When are atexit functions not called?¶

The callbacks registered with atexit are not invoked if:

  • the program dies because of a signal
  • os._exit() is invoked directly
  • a Python fatal error is detected (in the interpreter)

To illustrate a program being killed via a signal, we can modify one
of the examples from the subprocess article. There are 2 files
involved, the parent and the child programs. The parent starts the
child, pauses, then kills it:

import os
import signal
import subprocess
import time

proc = subprocess.Popen('atexit_signal_child.py')
print 'PARENT: Pausing before sending signal...'
time.sleep(1)
print 'PARENT: Signaling child'
os.kill(proc.pid, signal.SIGTERM)

The child sets up an atexit callback, to prove that it is not called.

import atexit
import time
import sys

def not_called():
    print 'CHILD: atexit handler should not have been called'

print 'CHILD: Registering atexit handler'
sys.stdout.flush()
atexit.register(not_called)

print 'CHILD: Pausing to wait for signal'
sys.stdout.flush()
time.sleep(5)

When run, the output should look something like this:

$ python atexit_signal_parent.py

CHILD: Registering atexit handler
CHILD: Pausing to wait for signal
PARENT: Pausing before sending signal...
PARENT: Signaling child

Note that the child does not print the message embedded in not_called().

Similarly, if a program bypasses the normal exit path it can avoid having the
atexit callbacks invoked.

import atexit
import os

def not_called():
    print 'This should not be called'

print 'Registering'
atexit.register(not_called)
print 'Registered'

print 'Exiting...'
os._exit(0)

Since we call os._exit() instead of exiting normally, the callback is not
invoked.

$ python atexit_os_exit.py

If we had instead used sys.exit(), the callbacks would still have been called.

import atexit
import sys

def all_done():
    print 'all_done()'

print 'Registering'
atexit.register(all_done)
print 'Registered'

print 'Exiting...'
sys.exit()
$ python atexit_sys_exit.py

Registering
Registered
Exiting...
all_done()

Simulating a fatal error in the Python interpreter is left as an exercise to
the reader.

Exceptions in atexit Callbacks¶

Tracebacks for exceptions raised in atexit callbacks are printed to the
console and the last exception raised is re-raised to be the final error
message of the program.

import atexit

def exit_with_exception(message):
    raise RuntimeError(message)

atexit.register(exit_with_exception, 'Registered first')
atexit.register(exit_with_exception, 'Registered second')

Notice again that the registration order controls the execution order. If an
error in one callback introduces an error in another (registered earlier, but
called later), the final error message might not be the most useful error
message to show the user.

$ python atexit_exception.py

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered second
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered first
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered first

In general you will probably want to handle and quietly log all exceptions in
your cleanup functions, since it is messy to have a program dump errors on
exit.

See also

atexit
The standard library documentation for this module.

Содержание

  1. PyMOTW
  2. Page Contents
  3. Navigation
  4. This Page
  5. Examples
  6. Navigation
  7. atexit – Call functions when a program is closing down¶
  8. Examples¶
  9. When are atexit functions not called?¶
  10. Exceptions in atexit Callbacks¶
  11. Navigation
  12. atexit — Program Shutdown Callbacks¶
  13. Registering Exit Callbacks¶
  14. Decorator Syntax¶
  15. Canceling Callbacks¶
  16. When Are atexit Callbacks Not Called?¶
  17. Handling Exceptions¶
  18. Error in atexit._run_exitfuncs after successful test run #1778
  19. Comments
  20. Footer
  21. atexit – Обратные вызовы завершения работы программы
  22. Регистрация обратных вызовов при выходе
  23. Синтаксис декоратора
  24. Отмена обратных вызовов
  25. Когда не вызываются обратные вызовы atexit?
  26. Обработка исключений

PyMOTW

If you find this information useful, consider picking up a copy of my book, The Python Standard Library By Example.

Page Contents

Navigation

This Page

Examples

The output from all the example programs from PyMOTW has been generated with Python 2.7.8, unless otherwise noted. Some of the features described here may not be available in earlier versions of Python.

If you are looking for examples that work under Python 3, please refer to the PyMOTW-3 section of the site.

Navigation

atexit – Call functions when a program is closing down¶

Purpose: Register function(s) to be called when a program is closing down.
Available In: 2.1.3 and later

The atexit module provides a simple interface to register functions to be called when a program closes down normally. The sys module also provides a hook, sys.exitfunc, but only one function can be registered there. The atexit registry can be used by multiple modules and libraries simultaneously.

Examples¶

A simple example of registering a function via atexit.register() looks like:

Since the program doesn’t do anything else, all_done() is called right away:

It is also possible to register more than one function, and to pass arguments. That can be useful to cleanly disconnect from databases, remove temporary files, etc. Since it is possible to pass arguments to the registered functions, we don’t even need to keep a separate list of things to clean up – we can just register a clean up function more than once.

Notice that order in which the exit functions are called is the reverse of the order they are registered. This allows modules to be cleaned up in the reverse order from which they are imported (and therefore register their atexit functions), which should reduce dependency conflicts.

When are atexit functions not called?¶

The callbacks registered with atexit are not invoked if:

  • the program dies because of a signal
  • os._exit() is invoked directly
  • a Python fatal error is detected (in the interpreter)

To illustrate a program being killed via a signal, we can modify one of the examples from the subprocess article. There are 2 files involved, the parent and the child programs. The parent starts the child, pauses, then kills it:

The child sets up an atexit callback, to prove that it is not called.

When run, the output should look something like this:

Note that the child does not print the message embedded in not_called().

Similarly, if a program bypasses the normal exit path it can avoid having the atexit callbacks invoked.

Since we call os._exit() instead of exiting normally, the callback is not invoked.

If we had instead used sys.exit(), the callbacks would still have been called.

Simulating a fatal error in the Python interpreter is left as an exercise to the reader.

Exceptions in atexit Callbacks¶

Tracebacks for exceptions raised in atexit callbacks are printed to the console and the last exception raised is re-raised to be the final error message of the program.

Notice again that the registration order controls the execution order. If an error in one callback introduces an error in another (registered earlier, but called later), the final error message might not be the most useful error message to show the user.

In general you will probably want to handle and quietly log all exceptions in your cleanup functions, since it is messy to have a program dump errors on exit.

atexit The standard library documentation for this module.

Navigation

© Copyright Doug Hellmann. | | Last updated on Jul 11, 2020. | Created using Sphinx. | Design based on «Leaves» by SmallPark |

Источник

atexit — Program Shutdown Callbacks¶

Purpose: Register function(s) to be called when a program is closing down.

The atexit module provides an interface to register functions to be called when a program closes down normally.

Registering Exit Callbacks¶

This is an example of registering a function explicitly by calling register() .

Because the program does not do anything else, all_done() is called right away.

It is also possible to register more than one function and to pass arguments to the registered functions. That can be useful to cleanly disconnect from databases, remove temporary files, etc. Instead of keeping a list of resources that need to be freed, a separate clean-up function can be registered for each resource.

The exit functions are called in the reverse of the order in which they are registered. This method allows modules to be cleaned up in the reverse order from which they are imported (and therefore register their atexit functions), which should reduce dependency conflicts.

Decorator Syntax¶

Functions that require no arguments can be registered by using register() as a decorator. This alternative syntax is convenient for cleanup functions that operate on module-level global data.

Because the function is registered as it is defined, it is also important to ensure that it works properly even if no other work is performed by the module. If the resources it is supposed to clean up were never initialized, calling the exit callback should not produce an error.

Canceling Callbacks¶

To cancel an exit callback, remove it from the registry using unregister() .

All calls to the same callback are canceled, regardless of how many times it has been registered.

Removing a callback that was not previously registered is not considered an error.

Because it silently ignores unknown callbacks, unregister() can be used even when the sequence of registrations might not be known.

When Are atexit Callbacks Not Called?¶

The callbacks registered with atexit are not invoked if any of these conditions is met:

  • The program dies because of a signal.
  • os._exit() is invoked directly.
  • A fatal error is detected in the interpreter.

An example from the subprocess section can be updated to show what happens when a program is killed by a signal. Two files are involved, the parent and the child programs. The parent starts the child, pauses, then kills it.

The child sets up an atexit callback, and then sleeps until the signal arrives.

When run, this is the output.

The child does not print the message embedded in not_called() .

If a program uses os._exit() , it can avoid having the atexit callbacks invoked.

Because this example bypasses the normal exit path, the callback is not run. The print output is also not flushed, so the example is run with the -u option to enable unbuffered I/O.

To ensure that the callbacks are run, allow the program to terminate by running out of statements to execute or by calling sys.exit() .

This example calls sys.exit() , so the registered callbacks are invoked.

Handling Exceptions¶

Tracebacks for exceptions raised in atexit callbacks are printed to the console and the last exception raised is re-raised to be the final error message of the program.

The registration order controls the execution order. If an error in one callback introduces an error in another (registered earlier, but called later), the final error message might not be the most useful error message to show the user.

It is usually best to handle and quietly log all exceptions in cleanup functions, since it is messy to have a program dump errors on exit.

Источник

Error in atexit._run_exitfuncs after successful test run #1778

Please see the bottom of this build log as an example. Additionally, my coverage for this is being reported by coveralls at 0%.

The text was updated successfully, but these errors were encountered:

Sorry, do you have any hints as to what might cause this in the code?

I don’t know if it’s anything in my code that could cause this. From a cursory glance at the error message, and multiprocessing/util.py , I’m fairly certain _logger for some reason or another is NoneType (possibly get_logger() was never called?) and thus the info(‘process shutting down’) call fails.

That all being said, I have never seriously used the multiprocessing package before and have never peeked into travis-ci ‘s source so I’m not sure what is going wrong where. Surely if no one else is seeing this message, a logger is being assigned in the code, right?

As stated below, it was a bug in multiprocessing/util.py as there was a call to info after it (and all module globals) were destroyed.

I have found the error; it is actually a bug in Python 2.7.3. It was patched in 2.7.4+ which is why I didn’t see it on my system (I am on 2.7.4) but showed up on the Travis run (because you guys still use Python 2.7.3 for py2.7; maybe you should look into upgrading that 😄 ).
The bug is referenced here, reported here, and patched here.
I simply do an import multiprocessing in my code to get it to not error out on exit.

That being said, my coverage is still being reported by coveralls as 0% on coveralls.io although I’m not sure who to blame for that one. You can close this ticket if you want, however, I would still like coverage to be reported correctly. =/ Coverage issues related to tox not working properly on Travis-CI for some reason; changed to just using py.test and works fine.

I am in talks with @dstufft about how we should handle upgrading our 2.7.x version. I will look into blogging about the progress soon.

When in doubt, we could build our own packages, though I’m fairly sure someone should have 2.7.5 or 2.7.4 packages available somewhere. Deadsnakes PPA doesn’t have them I think.

This should be fixed now w/ the new cookbooks.

Closing as Python 2.7 has since been updated.

© 2023 GitHub, Inc.

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Источник

atexit – Обратные вызовы завершения работы программы

Автор: Doug Hellmann
Дата записи

Зарегистрируйте функцию (ы), которая будет вызываться при закрытии программы.

Модуль atexit предоставляет интерфейс для регистрации функций, которые будут вызываться при нормальном завершении программы.

Регистрация обратных вызовов при выходе

Это пример явной регистрации функции путем вызова register () .

Поскольку программа больше ничего не делает, сразу вызывается all_done () .

Также можно зарегистрировать более одной функции и передавать аргументы зарегистрированным функциям. Это может быть полезно для полного отключения от баз данных, удаления временных файлов и т. Д. Вместо ведения списка ресурсов, которые необходимо освободить, для каждого ресурса можно зарегистрировать отдельную функцию очистки.

Функции выхода вызываются в порядке, обратном их регистрации. Этот метод позволяет очищать модули в порядке, обратном их импорту (и, следовательно, регистрировать свои функции atexit ), что должно уменьшить конфликты зависимостей.

Синтаксис декоратора

Функции, не требующие аргументов, могут быть зарегистрированы с помощью register () в качестве декоратора. Этот альтернативный синтаксис удобен для функций очистки, которые работают с глобальными данными на уровне модуля.

Поскольку функция регистрируется в том виде, в котором она определена, также важно убедиться, что она работает правильно, даже если модуль не выполняет никакой другой работы. Если ресурсы, которые предполагается очистить, никогда не инициализировались, вызов обратного вызова выхода не должен вызывать ошибки.

Отмена обратных вызовов

Чтобы отменить обратный вызов выхода, удалите его из реестра с помощью unregister () .

Все вызовы одного и того же обратного вызова отменяются, независимо от того, сколько раз он был зарегистрирован.

Удаление ранее не зарегистрированного обратного вызова не считается ошибкой.

Поскольку он молча игнорирует неизвестные обратные вызовы, unregister () может использоваться, даже если последовательность регистраций может быть неизвестна.

Когда не вызываются обратные вызовы atexit?

Обратные вызовы, зарегистрированные с помощью atexit , не вызываются, если выполняется любое из этих условий:

  • Программа умирает из-за сигнала.
  • os._exit () вызывается напрямую.
  • В интерпретаторе обнаружена фатальная ошибка.

Пример из раздела подпроцессов можно обновить, чтобы показать, что происходит, когда программа прерывается сигналом. Участвуют два файла: родительская и дочерняя программы. Родитель запускает ребенка, делает паузу, затем убивает его.

Потомок устанавливает обратный вызов atexit и затем засыпает, пока не поступит сигнал.

При запуске это результат.

Дочерний элемент не печатает сообщение, встроенное в not_called () .

Если в программе используется os._exit () , она может избежать вызова обратных вызовов atexit .

Поскольку в этом примере не используется обычный путь выхода, обратный вызов не выполняется. Вывод на печать также не сбрасывается, поэтому пример запускается с параметром -u , чтобы включить небуферизованный ввод-вывод.

Чтобы гарантировать выполнение обратных вызовов, позвольте программе завершить работу, закончив операторы для выполнения или вызвав sys.exit () .

В этом примере вызывается sys.exit () , поэтому вызываются зарегистрированные обратные вызовы.

Обработка исключений

Трассировки для исключений, возникающих в обратных вызовах atexit , выводятся на консоль, и последнее возникшее исключение повторно возникает, чтобы стать последним сообщением об ошибке программы.

Порядок регистрации контролирует порядок выполнения. Если ошибка в одном обратном вызове приводит к ошибке в другом (зарегистрированном ранее, но вызываемом позже), последнее сообщение об ошибке может быть не самым полезным сообщением об ошибке для показа пользователю.

Обычно лучше всего обрабатывать и незаметно регистрировать все исключения в функциях очистки, так как иметь ошибки дампа программы при выходе – это беспорядок.

  • стандартная библиотечная документация для atexit
  • Обработка исключений – глобальная обработка неперехваченных исключений.
  • Заметки о переносе Python 2 на 3 для atexit

Источник

When running bigchaindb with the command bigchaindb start and interrupting the process with CTRL-C, the following error shows up:

$ bigchaindb start
# ...
# ...
# ...
# CTRL-C
^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/multiprocessing/popen_fork.py", line 29, in poll
    pid, sts = os.waitpid(self.pid, flag)
KeyboardInterrupt
[2017-03-12 23:29:25 +0000] [34] [INFO] Handling signal: int

Related links

Listing a few links just in case it may be useful:

  • Python docs: signal, atexit, multiprocessing
  • http://stackoverflow.com/questions/9139127/why-is-my-threading-multiprocessing-python-script-not-exiting-properly#9143486
  • http://stackoverflow.com/questions/2546276/python-process-wont-call-atexit#2546397
  • http://stackoverflow.com/questions/39884898/large-amount-of-multiprocessing-process-causing-deadlock
  • http://stackoverflow.com/questions/19652446/python-program-with-thread-cant-catch-ctrlc
  • http://stackoverflow.com/questions/37692262/python-multiprocessing-assertionerror-can-only-join-a-child-process

Noteworthy

Quoting Martin Sústrik (original architect and lead developer of ØMQ), in http://aosabook.org/en/zeromq.html (thanks to @krish7919 for the link):

It turns out that shutting down a fully asynchronous system in a clean way is a dauntingly complex task. Trying to shut down a thousand moving parts, some of them working, some idle, some in the process of being initiated, some of them already shutting down by themselves, is prone to all kinds of race conditions, resource leaks and similar. The shutdown subsystem is definitely the most complex part of ØMQ. A quick check of the bug tracker indicates that some 30—50% of reported bugs are related to shutdown in one way or another.

Lesson learned: When striving for extreme performance and scalability, consider the actor model; it’s almost the only game in town in such cases. However, if you are not using a specialised system like Erlang or ØMQ itself, you’ll have to write and debug a lot of infrastructure by hand. Additionally, think, from the very beginning, about the procedure to shut down the system. It’s going to be the most complex part of the codebase and if you have no clear idea how to implement it, you should probably reconsider using the actor model in the first place.

I am using PIGPIO library to read temperature and humidity from a DHT22 sensor.
This is the script I am using.

import os
import sys
import time
import pigpio
pi = pigpio.pi()
import DHT22
s = DHT22.sensor(pi,4,17)
s.trigger()
time.sleep(0.2)
print("{} {} {:3.2f} {} {} {} {}".format(
    s.humidity(), s.temperature(), s.staleness(),
    s.bad_checksum(), s.short_message(), s.missing_message(),
    s.sensor_resets()))
s.cancel()
pi.stop()

the script runs well and return the temperature and humidity as expected. However, in my terminal I got the following error:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/home/pi/share/dht_py/pigpio_dht22/DHT22.py", line 238, in cancel
    self.pi.set_watchdog(self.gpio, 0)
  File "/usr/local/lib/python2.7/dist-packages/pigpio.py", line 1764, in set_watchdog
    self.sl, _PI_CMD_WDOG, user_gpio, int(wdog_timeout)))
  File "/usr/local/lib/python2.7/dist-packages/pigpio.py", line 983, in _pigpio_command
    sl.s.send(struct.pack('IIII', cmd, p1, p2, 0))
AttributeError: 'NoneType' object has no attribute 'send'
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/home/pi/share/dht_py/pigpio_dht22/DHT22.py", line 238, in cancel
    self.pi.set_watchdog(self.gpio, 0)
  File "/usr/local/lib/python2.7/dist-packages/pigpio.py", line 1764, in set_watchdog
    self.sl, _PI_CMD_WDOG, user_gpio, int(wdog_timeout)))
  File "/usr/local/lib/python2.7/dist-packages/pigpio.py", line 983, in _pigpio_command
    sl.s.send(struct.pack('IIII', cmd, p1, p2, 0))
AttributeError: 'NoneType' object has no attribute 'send'

What is the cause of this error and how to avoid that?
Thank you in advance.

Created on 2013-12-05 04:22 by vajrasky, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 8483 merged Anthony Sottile,
2018-07-26 15:43
PR 8684 merged miss-islington,
2018-08-06 08:28
PR 8685 merged miss-islington,
2018-08-06 08:28
Messages (14)
msg205273 — (view) Author: Vajrasky Kok (vajrasky) * Date: 2013-12-05 04:22
$ sudo adduser --no-create-home cutecat
Adding user `cutecat' ...
Adding new group `cutecat' (1007) ...
Adding new user `cutecat' (1005) with group `cutecat' ...
Not creating home directory `/home/cutecat'.
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for cutecat
Enter the new value, or press ENTER for the default
	Full Name []: 
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y

$ su cutecat
Password: 

$ ./python
Python 3.4.0b1 (default:1f1498fe50e5, Dec  5 2013, 09:48:25) 
[GCC 4.7.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Error in atexit._run_exitfuncs:
FileNotFoundError: [Errno 2] No such file or directory
$

Python 2.7 and 3.3 do not throw error.

$ ./python
Python 3.3.3+ (3.3:07425df887b5+, Dec  2 2013, 12:27:06) 
[GCC 4.7.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
[60778 refs]
[41580 refs]
$

$ ./python
Python 2.7.6+ (2.7:181ced5bf0be, Dec  4 2013, 11:23:42) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
$
msg205295 — (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-12-05 13:36
This is presumably due to the new default enabling of readline, where it is trying to save the history file when it exits.
msg205298 — (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-05 13:55
For the record, why did you close as invalid?
msg205300 — (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-12-05 13:58
Not sure who you meant by 'you', but just in case you meant me, Vajrasky was the one who closed it.
msg205304 — (view) Author: Vajrasky Kok (vajrasky) * Date: 2013-12-05 15:04
I closed it because I could not reproduce it anymore.

I think, it worked again after

$ ./python -S

I will open it again if I can consistently reproduce this bug.
msg205371 — (view) Author: Vajrasky Kok (vajrasky) * Date: 2013-12-06 13:49
Okay, this bug is valid. I can reproduce it in Ubuntu and Fedora.

bash-4.2$ ./python
Python 3.4.0b1 (default:7a668179d691, Dec  6 2013, 21:44:31) 
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Error in atexit._run_exitfuncs:
FileNotFoundError: [Errno 2] No such file or directory
bash-4.2$ ./python -S
Python 3.4.0b1 (default:7a668179d691, Dec  6 2013, 21:44:31) 
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
>>> 
bash-4.2$
msg205372 — (view) Author: Vajrasky Kok (vajrasky) * Date: 2013-12-06 13:54
Additional information:

When I created /home/cutecat with another user account.

bash-4.2$ ./python
Python 3.4.0b1 (default:7a668179d691, Dec  6 2013, 21:44:31) 
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Error in atexit._run_exitfuncs:
PermissionError: [Errno 13] Permission denied

Of course, so I change the ownership of /home/cutecat to cutecat. Then it works.

bash-4.2$ ./python
Python 3.4.0b1 (default:7a668179d691, Dec  6 2013, 21:44:31) 
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
bash-4.2$

So what did it try to do in /home/cutecat?

[sky@localhost cpython]$ ls -la /home/cutecat/
total 8
drwxr-xr-x. 2 cutecat root    4096 Dec  6 21:50 .
drwxr-xr-x. 4 root    root    4096 Dec  6 21:50 ..
-rw-------. 1 cutecat cutecat    0 Dec  6 21:50 .python_history

So I leave to core Python developers to decide whether this ticket is valid or not.
msg205373 — (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-06 13:56
The main question here is whether "interactive user without a home directory" is a valid / common use case. I think silencing the FileNotFoundError would be ok.

(however, the "home directory with wrong permissions" case sounds crazy)
msg218490 — (view) Author: Eric Ongerth (ejo) Date: 2014-05-13 23:06
I'm getting the same PermissionError 13:

Error in atexit._run_exitfuncs:
PermissionError: [Errno 13] Permission denied

My case is: I'm running Python 3.4.0 as a non-root user in a docker.io container built on ubuntu 14.04.  This user was created during the creation (Dockerfile) of the container.  The user has a home directory and that directory appears to have the usual/proper permissions.  When I exit the python3 REPL I get this error even if all I did was start python3 from the command line and then immediately exit.

So maybe the cause is other, or more subtle, than just a user with no home dir or home dir with unusual perms?
msg305161 — (view) Author: Andreas Krüger (dj3ei) Date: 2017-10-28 14:13
I can easily reproduce the problem with Docker,
and it does seem to be a permission problem:

    $ docker run -ti --rm --user="7777:7777" python:3.6.3-jessie bash -c "python3"
    Python 3.6.3 (default, Oct 10 2017, 02:29:16) 
    [GCC 4.9.2] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 
    Error in atexit._run_exitfuncs:
    PermissionError: [Errno 13] Permission denied

    $ docker run -ti --rm --user="7777:7777" python:3.6.3-jessie bash -c "HOME=/tmp python3; ls -lta /tmp"
    Python 3.6.3 (default, Oct 10 2017, 02:29:16) 
    [GCC 4.9.2] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 
    total 8
    drwxrwxrwt  2 root root 4096 Oct 28 14:10 .
    drwxr-xr-x 55 root root 4096 Oct 28 14:10 ..
    -rw-------  1 7777 7777    0 Oct 28 14:10 .python_history
msg322435 — (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2018-07-26 15:56
I was able to reproduce both the `PermissionError` and the `FileNotFoundError` under these circumstances:

$ docker run --user 123:123 -ti python python
Python 3.7.0 (default, Jul 17 2018, 11:04:33) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Error in atexit._run_exitfuncs:
PermissionError: [Errno 13] Permission denied


$ docker run --user nobody -ti python python
Python 3.7.0 (default, Jul 17 2018, 11:04:33) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Error in atexit._run_exitfuncs:
FileNotFoundError: [Errno 2] No such file or directory


In the former, the home directory is `/` (not writable).  In the latter, the homedir is `/nonexistent`, which, well, doesn't exist.

My patch addresses both of these errors.
msg323184 — (view) Author: Inada Naoki (methane) * (Python committer) Date: 2018-08-06 08:28
New changeset b2499669ef2e6dc9a2cdb49b4dc498e078167e26 by INADA Naoki (Anthony Sottile) in branch 'master':
bpo-19891: Ignore error while writing history file (GH-8483)
https://github.com/python/cpython/commit/b2499669ef2e6dc9a2cdb49b4dc498e078167e26
msg323186 — (view) Author: miss-islington (miss-islington) Date: 2018-08-06 09:03
New changeset 416f3435c536c5197f5c6a23504955cf717df200 by Miss Islington (bot) in branch '3.7':
bpo-19891: Ignore error while writing history file (GH-8483)
https://github.com/python/cpython/commit/416f3435c536c5197f5c6a23504955cf717df200
msg323187 — (view) Author: miss-islington (miss-islington) Date: 2018-08-06 09:15
New changeset e20d31cdb33bdfee68bce059f9a9c7ce71b035fe by Miss Islington (bot) in branch '3.6':
bpo-19891: Ignore error while writing history file (GH-8483)
https://github.com/python/cpython/commit/e20d31cdb33bdfee68bce059f9a9c7ce71b035fe
History
Date User Action Args
2022-04-11 14:57:55 admin set github: 64090
2018-08-06 09:42:26 methane set status: open -> closed
stage: patch review -> resolved
resolution: fixed
components:
+ Library (Lib), — Extension Modules
versions:
+ Python 3.7, Python 3.8, — Python 3.3, Python 3.4
2018-08-06 09:15:51 miss-islington set messages:
+ msg323187
2018-08-06 09:03:52 miss-islington set nosy:
+ miss-islington
messages:
+ msg323186
2018-08-06 08:28:51 miss-islington set pull_requests:
+ pull_request8180
2018-08-06 08:28:41 miss-islington set pull_requests:
+ pull_request8179
2018-08-06 08:28:30 methane set nosy:
+ methane
messages:
+ msg323184
2018-07-26 15:56:36 Anthony Sottile set nosy:
+ Anthony Sottile
messages:
+ msg322435
2018-07-26 15:43:00 Anthony Sottile set keywords:
+ patch
stage: patch review
pull_requests:
+ pull_request8005
2017-10-28 14:13:09 dj3ei set nosy:
+ dj3ei

messages:
+ msg305161
versions:
+ Python 3.6

2014-05-13 23:06:07 ejo set nosy:
+ ejo
messages:
+ msg218490
2013-12-06 13:56:12 pitrou set priority: normal -> low

messages:
+ msg205373
versions:
+ Python 3.3

2013-12-06 13:54:16 vajrasky set messages:
+ msg205372
2013-12-06 13:49:16 vajrasky set status: closed -> open
resolution: not a bug -> (no value)
messages:
+ msg205371
2013-12-05 15:04:33 vajrasky set messages:
+ msg205304
2013-12-05 13:58:56 r.david.murray set messages:
+ msg205300
2013-12-05 13:55:16 pitrou set messages:
+ msg205298
2013-12-05 13:36:05 r.david.murray set nosy:
+ r.david.murray, pitrou
messages:
+ msg205295
2013-12-05 08:37:24 vajrasky set status: open -> closed
resolution: not a bug
2013-12-05 04:22:10 vajrasky create

Автор оригинала: Doug Hellmann.

Цель:

Зарегистрируйте функцию (ы), которая будет вызываться при закрытии программы.

Модуль atexit предоставляет интерфейс для регистрации функций, которые будут вызываться при нормальном завершении программы.

Регистрация обратных вызовов при выходе

Это пример явной регистрации функции путем вызова register () .

atexit_simple.py

import atexit


def all_done():
    print('all_done()')


print('Registering')
atexit.register(all_done)
print('Registered')

Поскольку программа больше ничего не делает, сразу вызывается all_done () .

$ python3 atexit_simple.py

Registering
Registered
all_done()

Также можно зарегистрировать более одной функции и передавать аргументы зарегистрированным функциям. Это может быть полезно для полного отключения от баз данных, удаления временных файлов и т. Д. Вместо ведения списка ресурсов, которые необходимо освободить, для каждого ресурса можно зарегистрировать отдельную функцию очистки.

atexit_multiple.py

import atexit


def my_cleanup(name):
    print('my_cleanup({})'.format(name))


atexit.register(my_cleanup, 'first')
atexit.register(my_cleanup, 'second')
atexit.register(my_cleanup, 'third')

Функции выхода вызываются в порядке, обратном их регистрации. Этот метод позволяет очищать модули в порядке, обратном их импорту (и, следовательно, регистрировать свои функции atexit ), что должно уменьшить конфликты зависимостей.

$ python3 atexit_multiple.py

my_cleanup(third)
my_cleanup(second)
my_cleanup(first)

Синтаксис декоратора

Функции, не требующие аргументов, могут быть зарегистрированы с помощью register () в качестве декоратора. Этот альтернативный синтаксис удобен для функций очистки, которые работают с глобальными данными на уровне модуля.

atexit_decorator.py

import atexit


@atexit.register
def all_done():
    print('all_done()')


print('starting main program')

Поскольку функция регистрируется в том виде, в котором она определена, также важно убедиться, что она работает правильно, даже если модуль не выполняет никакой другой работы. Если ресурсы, которые предполагается очистить, никогда не инициализировались, вызов обратного вызова выхода не должен вызывать ошибки.

$ python3 atexit_decorator.py

starting main program
all_done()

Отмена обратных вызовов

Чтобы отменить обратный вызов выхода, удалите его из реестра с помощью unregister () .

atexit_unregister.py

import atexit


def my_cleanup(name):
    print('my_cleanup({})'.format(name))


atexit.register(my_cleanup, 'first')
atexit.register(my_cleanup, 'second')
atexit.register(my_cleanup, 'third')

atexit.unregister(my_cleanup)

Все вызовы одного и того же обратного вызова отменяются, независимо от того, сколько раз он был зарегистрирован.

$ python3 atexit_unregister.py

Удаление ранее не зарегистрированного обратного вызова не считается ошибкой.

atexit_unregister_not_registered.py

import atexit


def my_cleanup(name):
    print('my_cleanup({})'.format(name))


if False:
    atexit.register(my_cleanup, 'never registered')

atexit.unregister(my_cleanup)

Поскольку он молча игнорирует неизвестные обратные вызовы, unregister () может использоваться, даже если последовательность регистраций может быть неизвестна.

$ python3 atexit_unregister_not_registered.py

Обратные вызовы, зарегистрированные с помощью atexit , не вызываются, если выполняется любое из этих условий:

  • Программа умирает из-за сигнала.
  • os._exit () вызывается напрямую.
  • В интерпретаторе обнаружена фатальная ошибка.

Пример из раздела подпроцессов можно обновить, чтобы показать, что происходит, когда программа прерывается сигналом. Участвуют два файла: родительская и дочерняя программы. Родитель запускает ребенка, делает паузу, затем убивает его.

atexit_signal_parent.py

import os
import signal
import subprocess
import time

proc  subprocess.Popen('./atexit_signal_child.py')
print('PARENT: Pausing before sending signal...')
time.sleep(1)
print('PARENT: Signaling child')
os.kill(proc.pid, signal.SIGTERM)

Потомок устанавливает обратный вызов atexit и затем засыпает, пока не поступит сигнал.

atexit_signal_child.py

import atexit
import time
import sys


def not_called():
    print('CHILD: atexit handler should not have been called')


print('CHILD: Registering atexit handler')
sys.stdout.flush()
atexit.register(not_called)

print('CHILD: Pausing to wait for signal')
sys.stdout.flush()
time.sleep(5)

При запуске это результат.

$ python3 atexit_signal_parent.py

CHILD: Registering atexit handler
CHILD: Pausing to wait for signal
PARENT: Pausing before sending signal...
PARENT: Signaling child

Дочерний элемент не печатает сообщение, встроенное в not_called () .

Если в программе используется os._exit () , она может избежать вызова обратных вызовов atexit .

atexit_os_exit.py

import atexit
import os


def not_called():
    print('This should not be called')


print('Registering')
atexit.register(not_called)
print('Registered')

print('Exiting...')
os._exit(0)

Поскольку в этом примере не используется обычный путь выхода, обратный вызов не выполняется. Вывод на печать также не сбрасывается, поэтому пример запускается с параметром -u , чтобы включить небуферизованный ввод-вывод.

$ python3 -u atexit_os_exit.py

Registering
Registered
Exiting...

Чтобы гарантировать выполнение обратных вызовов, позвольте программе завершить работу, закончив операторы для выполнения или вызвав sys.exit () .

atexit_sys_exit.py

import atexit
import sys


def all_done():
    print('all_done()')


print('Registering')
atexit.register(all_done)
print('Registered')

print('Exiting...')
sys.exit()

В этом примере вызывается sys.exit () , поэтому вызываются зарегистрированные обратные вызовы.

$ python3 atexit_sys_exit.py

Registering
Registered
Exiting...
all_done()

Обработка исключений

Трассировки для исключений, возникающих в обратных вызовах atexit , выводятся на консоль, и последнее возникшее исключение повторно возникает, чтобы стать последним сообщением об ошибке программы.

atexit_exception.py

import atexit


def exit_with_exception(message):
    raise RuntimeError(message)


atexit.register(exit_with_exception, 'Registered first')
atexit.register(exit_with_exception, 'Registered second')

Порядок регистрации контролирует порядок выполнения. Если ошибка в одном обратном вызове приводит к ошибке в другом (зарегистрированном ранее, но вызываемом позже), последнее сообщение об ошибке может быть не самым полезным сообщением об ошибке для показа пользователю.

$ python3 atexit_exception.py

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "atexit_exception.py", line 11, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered second
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "atexit_exception.py", line 11, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered first

Обычно лучше всего обрабатывать и незаметно регистрировать все исключения в функциях очистки, так как иметь ошибки дампа программы при выходе – это беспорядок.

Смотрите также

  • стандартная библиотечная документация для atexit
  • Обработка исключений – глобальная обработка неперехваченных исключений.
  • Заметки о переносе Python 2 на 3 для atexit

Raspberry Pieman

unread,

Aug 16, 2022, 12:25:11 PM8/16/22

to VPython-users

Hi,

  I have recently installed vpython, using pip install vpython for my Python 3.9 on Windows/10 Home.

I tried to run this simple 2 line program:

import vpython
print(‘done’)

When run under Python 3.9 IDLE — it runs as expected.

However, if I try to run it on a CMD prompt window, I get the following error:

C:UsersRaspberryAppDataLocalProgramsPythonPython39>python Y:SourcePython_Python3vPythonvPythonintro.py
done
exit
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File «C:UsersRaspberryAppDataLocalProgramsPythonPython39libsite-packagesvpythonvpython.py», line 22, in Exit
    a = 1.0/zero
ZeroDivisionError: float division by zero

It seems to run OK, but falls over on the exit process.

If I comment-out the import vpython line — it runs with no error, so I know its related to vpython.

I have thousands of working Python programs and this is the first time I have been stumped for an answer.

Any ideas?

I eventually need to run it from VScode, but I need to resolve this first.

Stephen Spicklemire

unread,

Aug 16, 2022, 2:37:34 PM8/16/22

to ‘Ian Beatty’ via VPython-users, Steve Spicklemire

I’m not positive, but I think this may have been deliberately added at some point when some users were having trouble with windows cmd line programs hanging and not even allowing ctrl-c to interrupt them. I can try to go through the commits to see if there’s an explanation, but I guess the point is that this appears to be the intended behavior.

-steve

> —

> You received this message because you are subscribed to the Google Groups «VPython-users» group.

> To unsubscribe from this group and stop receiving emails from it, send an email to vpython-user…@googlegroups.com.

> To view this discussion on the web visit https://groups.google.com/d/msgid/vpython-users/b8cbedf1-40b7-437c-8d67-d4005dc3da18n%40googlegroups.com.

Raspberry Pieman

unread,

Aug 16, 2022, 6:07:44 PM8/16/22

to vpytho…@googlegroups.com

Steve,

     Thanks for looking into this.

I look forward to your findings.

If it is intended, then perhaps there should be some explanation in the documentation?

Martyn

Bruce Sherwood

unread,

Aug 16, 2022, 6:19:01 PM8/16/22

to VPython-users

There is indeed a problem with running a VPython program from a terminal. This modality works somewhat better if you add the following to the end of your program: «while True: rate(30)», though you may still have difficulty exiting.

Bruce

Bruce Sherwood

unread,

Aug 16, 2022, 6:39:27 PM8/16/22

to VPython-users

Correction: Instead of calling rate(), import time and add this to the end of your program:

while True: time.sleep(0.03)

I find on Windows that executing ctrl-c twice gets me out of the program. In any case, we’re not doing a good job of running VPython from a terminal.

Bruce

Bruce Sherwood

unread,

Aug 16, 2022, 7:35:30 PM8/16/22

to VPython-users

I forgot something. I think I’m using a corrected version of 7.6.4, in which at the end of the file ..Lib/site-packages/vpython/no_notebook.py Steve changed the while loop to this:

while not (httpserving and websocketserving): # try to make sure setup is complete
    time.sleep(0.1)

This doesn’t fix all the problems with running from a terminal but it does help.

Bruce

Aaron Titus

unread,

Aug 29, 2022, 3:25:52 AM8/29/22

to vpytho…@googlegroups.com

FYI I get the same error message.

I created an condo environment and installed vpython using:

conda install -c vpython vpython

I ran ipython and typed:

import vpython as vp

vp.sphere()

When I exit the browser tab with the vpython scene, I get the following error:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):

  File «/Users/atitus/opt/anaconda3/envs/ncsu/lib/python3.8/site-packages/vpython/vpython.py», line 22, in Exit

    a = 1.0/zero
ZeroDivisionError: float division by zero

And ipython exits after the error.

I’ll try installing a previous version of vpython to see if I can get around it.

Aaron

Я пытаюсь запустить простое приложение с несколькими процессами на Python. Основной поток порождает от 1 до N процессов и ждет, пока все они завершат обработку. Каждый процесс запускает бесконечный цикл, поэтому они потенциально могут работать вечно без какого-либо вмешательства пользователя, поэтому я добавил код для обработки KeyboardInterrupt:

#!/usr/bin/env python
import sys
import time
from multiprocessing import Process

def main():
    # Set up inputs..

    # Spawn processes
    Proc( 1).start()
    Proc( 2).start()

class Proc ( Process ):
    def __init__ ( self, procNum):
        self.id = procNum
        Process.__init__(self)

    def run ( self ):
        doneWork = False

        while True:

            try:
                # Do work...
                time.sleep(1)
                sys.stdout.write('.')

                if doneWork:
                    print "PROC#" + str(self.id) + " Done."
                    break

            except KeyboardInterrupt:
                print "User aborted."
                sys.exit()

# Main Entry
if __name__=="__main__":
    main()

Проблема в том, что при использовании CTRL-C для выхода я получаю дополнительную ошибку, хотя кажется, что процессы завершаются немедленно:

......User aborted.
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "C:Python26libatexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:Python26libmultiprocessingutil.py", line 281, in _exit_function
    p.join()
  File "C:Python26libmultiprocessingprocess.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:Python26libmultiprocessingforking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt
Error in sys.exitfunc:
Traceback (most recent call last):
  File "C:Python26libatexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:Python26libmultiprocessingutil.py", line 281, in _exit_function
    p.join()
  File "C:Python26libmultiprocessingprocess.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:Python26libmultiprocessingforking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt

Я использую Python 2.6 в Windows. Если есть лучший способ обработки многопроцессорности в Python, дайте мне знать.

Понравилась статья? Поделить с друзьями:
  • Error in action number 1 of create event for object
  • Error in accessing system registry you may not have enough permissions to modify registry
  • Error in a uploading bitrix
  • Error impossible constraint in asm
  • Error importing repomd xml for base damaged repomd xml file