1. Python / Говнокод #17277

    −121

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    #!/usr/bin/env python
    # encoding: utf-8
    
    import os
    import sys
    
    from sets import Set
    
    class OutputSplitter(object):
        """ splitter """
        
        def __init__(self, out_splitter):
            self.__pipes=None
            if isinstance(out_splitter, OutputSplitter):
                    self.__pipes = Set(out_splitter.pipes)
            elif out_splitter:
                print out_splitter
                if type(out_splitter) == list : #
                    for pn in out_splitter:
                        self.add_pipe(pn)
                else:
                    self.add_pipe(out_splitter)
                       
        @property
        def pipes(self):
            return self.__pipes
        
        def add_pipe(self, pn):
            if isinstance(pn, basestring):
                if pn == 'stderr': x = sys.stderr
                elif pn == 'stdout': x = sys.stdout
                else: 
                    p = os.path.dirname(pn)
                    if p and not os.path.exists(p):
                        os.makedirs(p)
                    try: 
                        x = open(pn,'w+')
                    except IOError:
                        raise
                        
            else: x = pn
            
            if hasattr(x, 'write') and hasattr(x, 'flush'):
                if self.__pipes is None:
                    self.__pipes=Set()
                self.__pipes.add(x)
        
        def write(self,s):
            if self.__pipes:
                for p in self.__pipes:
                    p.write(s)
        
        def flush(self):
            if self.__pipes:
                for p in self.__pipes:
                    p.flush()
        
        #def __enter__(self):
        #    pass         
        #def __exit__(self, exc_type, exc_value, traceback):
        #    pass
    
    if __name__ == '__main__':
        cout=sys.stdout if True else sys.stderr
        o=OutputSplitter(cout)
        pass

    Испаравленная версия по монивам http://govnokod.ru/17181. Учтены замечания некого Анонимус http://govnokod.ru/17181#comment256577. Надеюсь что будут еще замечания, такие же конструктивные и полезные.

    Запостил: apgurman, 08 Декабря 2014

    Комментарии (28) RSS

    • > self.__pipes=None
      > if self.__pipes is None:
      > if self.__pipes:
      Нахуя все эти свистопляски с None? Сунул бы туда пустой Set в конструкторе, да и всё. Кода было бы на порядок меньше. Даже в жабе рекомендуют юзать пустые коллекции вместо null'ов.
      Ответить
      • Этот я уже объяснял. Мне if self.__pipes is None: больше нравится чем len(self.__pipes)
        Ответить
        • Пустой список, Set и т.п. считаются ложью, не надо там никаких len:
          if self.__pipes:
          Ответить
          • Согласен Завтра с утра подумаю почему я еще так решил когда писал и если других причин нет поправлю. Спасибо))
            Ответить
          • Наверно экономил на конструкторе Set() Жадный я Признаю))
            Ответить
    • Тут коллеги на другом форуме написали:
      Files opened are not closed. In fact, it might be a good idea to open/close file handles using __enter__() and __exit__() methods, which need to be defined for this class.
      Что-то у меня никак в переопределенный метод __exit__() управление не передается. Почему?
      Ответить
      • Ответить
      • Хрен знает, короче. У меня работает:
        class OutputSplitter(object):
            def __enter__(self):
                print "Enter"
                return self
            def __exit__(self, exc_type, exc_value, traceback):
                print "Exit. Closing files..."
            def test(self):
                print "Test!"
        
        with OutputSplitter() as os:
            os.test()
        http://ideone.com/iL8t5S
        Ответить
        • Да именно с with xxx as x: и работает. Спасибо, Борман!
          Ответить
          • Пожалуйста. Только вот я не въеду, каким местом ты читал доку и как у тебя __enter__() то вызвался без with...
            Ответить
            • он тоже не вызывался
              Ответить
              • Ааа, вон как. Просто по "Что-то у меня никак в переопределенный метод __exit__() управление не передается" кажется, что только __exit__().
                Ответить
            • теперь вот думаю как красиво учесть открытые pipes, чтобы потом закрыть. Сразу возникает желание все усложнить, но добавить функциональность и разрешить добавлять уже окрытые. Соответственно ... В общем из скрипта на час писанины вышла целая наука по написанию правильных программ и библиотек на Python. В общем-то что и было основной задачей))
              Ответить
              • > учесть открытые pipes, чтобы потом закрыть
                Ну самый тупой вариант - второй Set или list, в который добавлять пайпы, которые OutputSplitter запилил сам и должен закрыть.

                > правильных программ и библиотек на Python
                Тогда еще придется прочесть PEP-8, работу с pip и о создании пакетов...
                Ответить
                • сделал примерно так:
                  def __init__(self, out_splitter):
                          self.file_to_close=[]
                          # bla bla bla
                  
                      def add_pipe(self, pn):
                            #bla bla bla
                                  try: 
                                      x = open(pn,'w+')
                                      self.file_to_close.append(x)
                                  except IOError:
                                      raise
                  
                      #bla bla bla
                      def __enter__(self): return self
                      
                      def __exit__(self, exc_type, exc_value, traceback):
                          for f in self.file_to_close: f.close()
                  Ответить
                • И Set там лишним будет
                  Ответить
                • Наверно нужно было еще в try exept обернуть
                  Ответить
                  • close()? Ну наверное. Не помню как в питоне, но в других языках он вполне так кидает исключения.

                    Сделай еще метод close() своему OutputSplitter'у, чтобы можно было вручную позакрывать, без with. А из __exit__ его вызовешь.
                    Ответить
                    • Хорошая идея Спасибо!
                      Ответить
                    • В путхоне даже можно self.__exit__ = self.close
                      Ответить
                      • А нафига self? Вроде же без них надо:
                        class Foo:
                            def close(self):
                                # ...
                        
                            __exit__ = close
                        P.S. И там аргументы же другие, у __exit__ их дохрена.
                        Ответить
    • Есть же форум...
      Ответить
      • А вот тут есть нюанс. На форуме ты не знаешь степень квалифицированности отвечающего - борманд ли это, либо же хомячок. По этой же причине я не проявляю на форуме активности. А ведь хочется же иногда задать вопрос людям, которых заочно записал в группу "о, а этот чувак говна не посоветует"!
        Ответить
        • http://www.programmersforum.ru/showthread.php?t=241647
          Предпоследний пост. Читай очень внимательно.
          Ответить
          • Стертор не палится. Хотя крупицы правды в посте есть.
            Ответить
        • Если ты про gvforum - там те же люди зарегены, просто туда не ходит никто.
          Ответить

    Добавить комментарий