Установить атрибут «Только для чтения» в Python?

Учитывая динамический Python, я буду потрясен, если это не так возможно:

Я хотел бы изменить реализацию sys.stdout.write .

Я получил эту идею от ответа на другой вопрос: https://stackoverflow.com/a/24492990/901641

Я попытался просто написать это:

 original_stdoutWrite = sys.stdout.write def new_stdoutWrite(*a, **kw): original_stdoutWrite("The new one was called! ") original_stdoutWrite(*a, **kw) sys.stdout.write = new_stdoutWrite 

Но это говорит мне AttributeError: 'file' object attribute 'write' is read-only .

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

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

  • Прочитать консольный вывод другой программы в Python
  • Python - разница между sys.stdout.write и печатью
  • Как реплицировать поведение tee в Python при использовании подпроцесса?
  • Сохранение stdout из subprocess.Popen в файл, плюс запись большего количества материала в файл
  • удалить последнюю строку STDOUT в Python
  • Получение всей информации из подпроцесса.
  • Как отключить и снова включить ведение журнала консоли в Python?
  • Получение результата в реальном времени из ffmpeg для использования в индикаторе выполнения (PyQt4, stdout)
  • 2 Solutions collect form web for “Установить атрибут «Только для чтения» в Python?”

    Несмотря на свою динамичность, Python не разрешает использовать встроенные типы обезьян, такие как file . Это даже мешает вам сделать это, изменив __dict__ такого типа – свойство __dict__ возвращает dict, завернутый в прокси-сервер, доступный только для чтения, поэтому оба назначения file.write и file.__dict__['write'] file.write с ошибкой. И по крайней мере две веские причины:

    1. код C ожидает, что встроенный тип file соответствует структуре типа PyFile , а file.write к функции PyFile_Write() используемой внутренне.

    2. Python реализует кэширование доступа атрибутов к типам, чтобы ускорить поиск метода и создание метода экземпляра. Этот кеш был бы сломан, если бы ему было разрешено напрямую назначать тип dicts.

    Разумеется, исправление для Monkey допускается для классов, реализованных в Python, которые отлично справляются с динамическими изменениями.

    Однако … если вы действительно знаете, что делаете, вы можете использовать низкоуровневые API, такие как ctypes чтобы подключиться к реализации и перейти к типу dict. Например:

     # WARNING: do NOT attempt this in production code! import ctypes def magic_get_dict(o): # find address of dict whose offset is stored in the type dict_addr = id(o) + type(o).__dictoffset__ # retrieve the dict object itself dict_ptr = ctypes.cast(dict_addr, ctypes.POINTER(ctypes.py_object)) return dict_ptr.contents.value def magic_flush_mro_cache(): ctypes.PyDLL(None).PyType_Modified(ctypes.py_object(object)) # monkey-patch file.write dct = magic_get_dict(file) dct['write'] = lambda f, s, orig_write=file.write: orig_write(f, '42') # flush the method cache for the monkey-patch to take effect magic_flush_mro_cache() # magic! import sys sys.stdout.write('hello world\n') 

    Несмотря на то, что Python в основном является динамическим языком, существуют такие типы объектов, как str , file (включая stdout ), dict и list , которые фактически реализованы на низкоуровневом C и полностью статичны:

     >>> a = [] >>> a.append = 'something else' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object attribute 'append' is read-only >>> a.hello = 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object has no attribute 'hello' >>> a.__dict__ # normal python classes would have this Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object has no attribute '__dict__' 

    Если ваш объект является родным C-кодом, ваша единственная надежда заключается в использовании реального обычного класса. Для вашего случая, как уже упоминалось, вы можете сделать что-то вроде:

     class NewOut(type(sys.stdout)): def write(self, *args, **kwargs): super(NewOut, self).write('The new one was called! ') super(NewOut, self).write(*args, **kwargs) sys.stdout = NewOut() 

    или, чтобы сделать что-то похожее на ваш исходный код:

     original_stdoutWrite = sys.stdout.write class MyClass(object): pass sys.stdout = MyClass() def new_stdoutWrite(*a, **kw): original_stdoutWrite("The new one was called! ") original_stdoutWrite(*a, **kw) sys.stdout.write = new_stdoutWrite 
    Interesting Posts

    Каков лучший способ передать данные в Python Unittest, перенаправленный STDIN или Pickle?

    Ошибка инициализации объекта Python. Или я не понимаю, как работают объекты?

    Выполнение многострочных операторов Python в однострочной командной строке

    Pyro4 не позволяет более чем двум клиентам получить доступ к одному URI

    Пример формы электронной почты Python Django

    Ошибка Apache mod_wsgi: Запрещено У вас нет прав доступа / доступа на этом сервере

    Приложение Bundle Python без интерпретатора

    Почему некоторые функции подчеркивают «__» до и после имени функции?

    thread.start_new_thread vs threading.Thread.start

    Как правильно управлять памятью с помощью ZODB?

    Как изменить размер шрифта тиков объекта axes в matplotlib

    Как получить URL-адрес не-ascii с помощью urlopen Python?

    Как проверить, является ли объект разборчивым

    как объединить два кадра данных в python pandas

    Как создать отдельную колонку отслеживания на основе дат?

    Python - лучший язык программирования в мире.