В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.
При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.
Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».
Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this
. Возьмем этот пример:
public class Some {
private int id;
public int getId(){
return this.id;
}
public setId( int newId ) {
this.id = newId;
}
}
И в другом месте вашего кода:
Some reference = new Some(); // Point to a new object of type Some()
Some otherReference = null; // Initiallly this points to NULL
reference.setId( 1 ); // Execute setId method, now private var id is 1
System.out.println( reference.getId() ); // Prints 1 to the console
otherReference = reference // Now they both point to the only object.
reference = null; // "reference" now point to null.
// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );
// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...
Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference
и otherReference
оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.
У меня есть модуль, который я использую для таких ситуаций - куда процесс будет работать в течение долгого времени, но иногда застревает по неизвестным и невоспроизводимым причинам. Это - немного hacky, и только работает над Unix (требует сигналов):
import code, traceback, signal
def debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
i = code.InteractiveConsole(d)
message = "Signal received : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.SIGUSR1, debug) # Register handler
Для использования просто назовите слушать () функция в какой-то момент, когда программа запускает (Вы могли даже придерживаться, это в site.py для имения всех программ Python использует его), и позвольте ему работать. В любой точке отправьте процессу сигнал SIGUSR1, использование уничтожает, или в Python:
os.kill(pid, signal.SIGUSR1)
Это заставит программу повреждаться к консоли Python в точке, в которой это в настоящее время, показывая Вам отслеживание стека и разрешение Вам управлять переменными. Используйте управление-d (EOF), чтобы продолжить работать (хотя примечание, что Вы, вероятно, прервете любой ввод-вывод и т.д. в точке, о которой Вы предупреждаете, таким образом, это не полностью ненавязчиво.
у меня есть другой сценарий, который делает то же самое, кроме него связывается с рабочим процессом через канал (для обеспечения отладки фоновых процессов и т.д.). Это является немного большим для регистрации здесь, но я добавил его как рецепт .
поваренной книги Python Предложение для установки обработчика сигналов является хорошим, и я использую его много. Например, bzr значением по умолчанию устанавливает обработчик SIGQUIT, который вызывает pdb.set_trace()
для непосредственного бросания Вас в подсказка pdb. (См. источник bzrlib.breakin модуля для точных деталей.) С pdb можно не только получить текущее отслеживание стека, но также и осмотреть переменные, и т.д.
Однако иногда я должен отладить процесс, в котором у меня не было предвидения для установки обработчика сигналов. На Linux можно присоединить gdb к процессу и получить отслеживание стека Python с некоторыми gdb макросами. Помещенный http://svn.python.org/projects/python/trunk/Misc/gdbinit в ~/.gdbinit
, тогда:
gdb -p
PID
pystack
Это не полностью надежно, к сожалению, но это работает большую часть времени.
Наконец, присоединяя strace
может часто давать Вам хорошую идею, что делает процесс.
Я не знаю ни о чем подобном ответ Java на SIGQUIT, таким образом, Вам, возможно, придется создать его в к Вашему приложению. Возможно, Вы могли сделать сервер в другом потоке, который может получить stacktrace на ответе на сообщение некоторого вида?
Нет никакого способа сцепиться в под управлением Python, обрабатывают и получают разумные результаты. То, что я делаю, если процессы запираются, сцепляет strace в и пытается выяснить то, что точно происходит.
, К сожалению, часто strace является наблюдателем, который "фиксирует" условия состязания так, чтобы вывод был бесполезен там также.
На это стоит посмотреть Pydb, "расширенная версия отладчика Python свободно на основе gdb набора команд". Это включает менеджеров по сигналу, которые могут заботиться о запуске отладчика, когда указанный сигнал отправляется.
Лето А 2006 года проекта Кода, на который посмотрели, добавляя удаленные функции отладки к pydb в модуле, названном mpdb.
python-dv yourscript.py
, Который сделает интерпретатор, чтобы работать в режиме отладки и дать Вам трассировку того, что делает интерпретатор.
, Если Вы хотите в интерактивном режиме отладить код, необходимо выполнить его как это:
python-m pdb yourscript.py
, Который говорит интерпретатору Python выполнять Ваш сценарий с модулем "pdb", который является отладчиком Python при выполнении его как этот интерпретатор будет выполняться в интерактивном режиме, во многом как GDB
Что действительно помогло мне, вот подсказка темной личности (который я проголосовал бы и комментарий, если бы у меня были точки репутации) для того, чтобы вытащить отслеживание стека из неподготовленный процесс Python. Кроме него не работал, пока я не изменил gdbinit сценарий . Так:
загрузка http://svn.python.org/projects/python/trunk/Misc/gdbinit и помещенный это в ~/.gdbinit
редактирует его, изменяясь [редактирование: больше необходимый; связанный файл уже имеет это изменение с 14.01.2010] PyEval_EvalFrame
к PyEval_EvalFrameEx
Присоединение gdb: gdb -p PID
Получают отслеживание стека Python: pystack
модуль traceback имеет некоторые хорошие функции среди них: print_stack:
import traceback
traceback.print_stack()
>>> import traceback
>>> def x():
>>> print traceback.extract_stack()
>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]
можно также приятно отформатировать отслеживание стека, видеть эти документы .
Редактирование : Для моделирования поведения Java, как предложено @Douglas Leeder, добавляет, это:
import signal
import traceback
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
к запуску кодируют в Вашем приложении. Тогда можно распечатать стек путем отправки SIGUSR1
к рабочему процессу Python.
Я почти всегда имею дело с несколькими потоками, а основной поток, как правило, мало что делает, поэтому наиболее интересно выгрузить все стеки ( что больше похоже на дамп Java). Вот реализация на основе этого блога :
import threading, sys, traceback
def dumpstacks(signal, frame):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
использовать модуль inspect.
import inspect помощь (inspect.stack) Справка по стеку функций в модуле inspect:
stack (context = 1) Вернуть список записей для стека над кадром вызывающего.
Я считаю это действительно очень полезным.