Как регистрировать все, что происходит в сеансе интерактивной оболочки Python? - PullRequest
7 голосов
/ 08 ноября 2011

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

>>> 5 * 7
35
>>> print("Hello, world!")
Hello, world!
>>> "Hello, world!"
'Hello, world!'

Я хотел бы видеть следующее в файле журнала:

> 5 * 7
35
> print("Hello, world!")
Hello, world!
> "Hello, world!"
'Hello, world!'

Форматирование не имеет значения;важно то, что я могу искать в файле ключевые слова, чтобы вызвать интерактивные события во время сеанса.

То, что я узнал до сих пор, пытается это сделать:

Модуль Python codeмне создать InteractiveConsole объект, метод raw_input, который я могу переопределить для входа в файл, например так:

import code
class LoggedConsole(code.InteractiveConsole):
  def __init__(self, locals):
    super(LoggedConsole, self).__init__(locals)
    self.file = open('consolelog.dat', 'a')

  def __del__(self):
    self.file.close()

  def raw_input(self, prompt=""):
    data = input(prompt)
    self.file.write(data+'\n')
    return data

Кроме того, InteractiveConsole использует встроенный writeметод регистрации ошибок, который я могу переопределить:

def write(self, data):
  sys.stderr.write(data)
  self.file.write(data+'\n')

Я также узнал, что следующий фрагмент будет записывать весь стандартный вывод:

class Tee(object):
  def __init__(self):
    self.file = open('consolelog.dat', 'a')
    self.stdout = sys.stdout

  def __del__(self):
    sys.stdout = self.stdout
    self.file.close()

  def write(self, data):
    self.file.write(data)
    self.stdout.write(data)

sys.stdout = Tee()

Моя (неработающая) попытка принестивсе это было вместе, чтобы затем создать LoggedConsole объект и передать его Tee в локальных.

console = LoggedConsole(locals={sys.stdout:LoggedExec()})
console.interact()

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

В любом случае, это откроет новую интерактивную консоль и запишет (после закрытия) все входные данные и ошибки, но не выходные.Я бился головой об это некоторое время, и я чувствую, что я рядом, но, может быть, даже нет.

Кроме того, есть ли способ, чтобы все это произошло во время сеанс?В настоящее время все ведение журнала происходит после закрытия сеанса.

Спасибо за ваше время, извините за стену текста.

edit: я хотел бы иметь возможность выполнить это в стандартеИнтерпретатор Python для переносимости.

edit2: Фрагмент Jaime очень хорошо работает для регистрации всего, что мне нужно.Как бы то ни было, чтобы я мог сделать это в реальном времени, вместо того, чтобы ждать закрытия сессии?

edit3: Понял это :).Финальный рабочий фрагмент:

import code
import sys

class Tee(object):
  def __init__(self, log_fname, mode='a'):
    self.log = open(log_fname, mode)

  def __del__(self):
    # Restore sin, so, se
    sys.stdout = sys.__stdout__
    sys.stdir = sys.__stdin__
    sys.stderr = sys.__stderr__
    self.log.close()

  def write(self, data):
    self.log.write(data)
    self.log.flush()
    sys.__stdout__.write(data)
    sys.__stdout__.flush()

  def readline(self):
    s = sys.__stdin__.readline()
    sys.__stdin__.flush()
    self.log.write(s)
    self.log.flush()
    return s

  def flush(foo):
    return

sys.stdout = sys.stderr = sys.stdin = Tee('consolelog.dat', 'w')

console = code.InteractiveConsole()
console.interact()

Ответы [ 5 ]

8 голосов
/ 08 ноября 2011

Я проверял это только в python2.7. У меня нет 3 под рукой.

import code
import sys

class Tee(object):

  def __init__(self, log_fname, mode='a'):
    self.log = open(log_fname, mode)

  def __del__(self):
    # Restore sin, so, se
    sys.stdout = sys.__stdout__
    sys.stdir = sys.__stdin__
    sys.stderr = sys.__stderr__
    self.log.close()

  def write(self, data):
    self.log.write(data)
    sys.__stdout__.write(data)

  def readline(self):
    s = sys.__stdin__.readline()
    self.log.write(s)
    return s

# Tie the ins and outs to Tee.
sys.stdout = sys.stderr = sys.stdin = Tee('consolelog.dat', 'w')

console = code.InteractiveConsole()
console.interact()
5 голосов
/ 08 ноября 2011

взгляните на IPython (сам не использовал). Вот раздел в документации, который может представлять особый интерес: http://ipython.org/ipython-doc/dev/interactive/reference.html#session-logging-and-restoring

3 голосов
/ 08 ноября 2011

См. эту статью Virtualenv Дуга Хеллмана, показывающую, как записать сеанс iPython :

Если вам удобно работать с интерактивной подсказкой таким образом, но вы хотите записать, что вы делаете для дальнейшего использования после закрытия сеанса, вы можете использовать функцию ведения журнала IPython, чтобы записать сеанс в файл. Чтобы активировать журнал, используйте управляющую команду %logstart, как показано в листинге 5. Выходной файл является исходным файлом Python, поэтому его легко очистить и превратить в «настоящий» модуль, когда вы закончите экспериментировать. .

In [6]: %logstart
Activating auto-logging. Current session state plus future input saved.
Filename       : ipython_log.py
Mode           : rotate
Output logging : False
Raw input log  : False
Timestamping   : False
State          : active

In [7]: a = 5

In [8]: b = 6

In [9]: c = a * b

In [10]: c

Out[10]: 30

In [11]: d = [ a, b, c]

In [12]: d

Out[12]: [5, 6, 30]

In [13]: %logstop
2 голосов
/ 14 декабря 2013

Вы можете просто использовать команду сценария unix, попробуйте:

script -a filename.txt
python
>> print("hi")
hi
>> exit()
exit

filename.txt запишет все, что вы делали в этом сеансе, это будет выглядеть примерно так:

Script started on Sat Dec 14 11:18:41 2013
python
>> print('hi')
hi
>> exit()
exit

Script done on Sat Dec 14 11:18:59 2013
0 голосов
/ 07 апреля 2014

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

https://github.com/hholst80/loginteractive

Работает, используя LD_PRELOAD для передачи stdin.txt (или $ STDIN) в stdout. Это работает для питона и октавы, хотя я еще не тестировал , что очень много.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...