• Как в TornadoWeb (Python3) обрабатывать присланные картинки?

    @7j7
    Часть прямо из проекта !!!

    __author__ = 'vadim7j7'
    # ----------------------------------------------------------------------------------------------------------------------
    import multiprocessing
    from os.path import join, isfile
    from os import unlink
    from io import BytesIO
    
    import tornado.gen
    from concurrent.futures import ThreadPoolExecutor
    from tornado.concurrent import run_on_executor
    from PIL import Image
    
    from app import BaseHandler
    from app.modules.helpers import gen_ran_name, crop_img
    from app.sql_raw_methods.User import get_user_info, update_user_photo
    
    
    # ----------------------------------------------------------------------------------------------------------------------
    class UpFile(BaseHandler):
        executor = ThreadPoolExecutor(max_workers=multiprocessing.cpu_count())
    
        def __init__(self, application, request, **kwargs):
            super().__init__(application, request, **kwargs)
            self.path_constants = {
                '1': self.settings['tmp_path'],
                '2': self.settings['tmp_path'],
                '3': self.settings['user_avatars']}
    
        @tornado.gen.coroutine
        def post(self):
            self._data['dateType'] = 'json'
            if self.request.files['file']:
                if len(self.request.files['file'][0]['body']) <= 12000000:
                    try:
                        thumbnail = yield self.make_thumbnail(self.request.files['file'][0]['body'])
                    except IOError as er:
                        self._data['status'] = 500
                    else:
                        self._data['body'] = thumbnail
                        if self.get_argument("dataTypeObject") == '3':
                            yield self.rewrite_user_avatar(thumbnail)
    
            self.render(None)
    
        def delete(self):
            self._data['dateType'] = 'json'
            name = self.get_argument('file', None)
            from_remove = self.get_argument('from_remove', 'tmp')
            if name is not None:
                patch_file_tmp = join(self.settings['static_path'], from_remove, name)
                if isfile(patch_file_tmp):
                    unlink(patch_file_tmp)
                    self._data['body'] = 'Ok'
                else:
                    self._data['status'] = 404
                    self._data['body'] = 'Not file is tmp'
            else:
                self._data['status'] = 301
                self._data['body'] = 'Not correct request'
    
            self.render(None)
    
        @run_on_executor
        def make_thumbnail(self, content):
            im = Image.open(BytesIO(content))
            path_out = self.path_constants[self.get_argument('dataTypeObject')]
    
            with BytesIO() as output:
                new_name = '%s.JPEG' % gen_ran_name()
                patch_file_tmp = join(path_out, new_name)
    
                if self.get_argument("dataTypeObject") == '3':
                    src_width, src_height = im.size
                    im = crop_img(im, src_width, src_height, 128, 128)
    
                im.convert('RGB').save(patch_file_tmp, 'JPEG', quality=100, optimize=True)
                del im
    
                return new_name
    
        @tornado.gen.coroutine
        def rewrite_user_avatar(self, photo):
            cursor = yield self.db.execute(get_user_info(self.current_user['id'], 'photo'))
            user = cursor.fetchone()
    
            if user[0]:
                old_avatar_path = join(self.path_constants.get('3'), user[0])
                if isfile(old_avatar_path):
                    unlink(old_avatar_path)
                yield self.db.execute(update_user_photo(self.current_user['id'], photo))
    
    
    # ----------------------------------------------------------------------------------------------------------------------
    
    def crop_img(original_img, src_width, src_height, max_width, max_height):
        if max_width <= 0:
            max_width = max_height * src_width / src_height
    
        if max_height <= 0:
            max_height = max_width * src_height / src_width
    
        src_ratio = float(src_width) / float(src_height)
        dst_width, dst_height = max_width, max_height
        dst_ratio = float(dst_width) / float(dst_height)
    
        if dst_ratio < src_ratio:
            crop_height = src_height
            crop_width = crop_height * dst_ratio
            x_offset = float(src_width - crop_width) / 2
            y_offset = 0
        else:
            crop_width = src_width
            crop_height = crop_width / dst_ratio
            x_offset = 0
            y_offset = float(src_height - crop_height) / 3
    
        preview_img = original_img.crop((int(x_offset), int(y_offset),
                                         int(x_offset + int(crop_width)),
                                         int(y_offset) + int(crop_height))).resize((int(dst_width), int(dst_height)), 1)
    
        return preview_img
    Ответ написан
    3 комментария
  • Swift: как сохранить ссылку на другой объект в параметрах класса?

    Flanker_4
    @Flanker_4
    У меня ваша версия вообще не собралась. Вот так нормально. Предположу, что проблема в inout и в том что передаваемый параметр объявлен не с тем типом явно (optional или !). От ! типов вообще лучше отказаться и поменьше их использовать, это скорей костыль.

    class List:NSObject{
        internal var name:String?
    }
    
    
    class RecordsList: NSObject {
        
        var listObj: List?
        
        init (inout list: List?)
        {
            self.listObj = list
        }
        func printData()
        {
            println(self.listObj?.name)
        }
    }
    
            var listObject:List? = List()
            listObject?.name = "FirstValue"
            
            var RL = RecordsList(list: &listObject)
            listObject?.name = "Second Value"
            
            RL.printData()

    Вот так норм
    Ответ написан
    4 комментария
  • Swift: как сохранить ссылку на другой объект в параметрах класса?

    @rsi
    software engineer
    А это точно верный листинг? Вы как то лихо RL создали, ни var ни let или теперь так можно?
    Ответ написан
    5 комментариев
  • Postgres(PostGis) VS Mongodb: сравнение пространственных индексов. Кто быстрее?

    antimirov
    @antimirov
    Если у вас уже все данные в постгресе, то я не вижу смысла использовать Mongo для задач GIS. Круче PostGIS-а сейчас ничего бесплатного нет. По скорости вряд ли будут какие-то различия, индексы, по идее, обе системы использую аналогичные, с одинаковым Big O. Наоборот, выиграете из-за отсутствия необходимости туда-сюда гонять данные.
    Ответ написан
    Комментировать
  • Как получить опыт для устройства на работу Python Developer?

    alexiusp
    @alexiusp
    senior frontend developer
    Соглашусь с вышенаписанным, что в вебе конкретный язык для джуниора не имеет особого значения - всегда можно переучиться. По своему, пусть небольшому, опыту могу сказать, что я и мои коллеги всегда смотрим на базовые знания соответствующих технологий. Я спрашиваю про ООП, MVC, какие-то особенности работы веб приложений. Мой коллега при поиске ораклиста спрашивал сколько нужно таблиц, чтобы описать некоторую предметную область (маленькую разумеется).
    А по поводу, где набираться опыта, у меня есть своя хитрость. Можно устроиться в бюджетную организацию, где есть свой отдел разработки. Я начинал в вузе. Если повезёт найти место, где активно занимаются разработкой всяких новых фишек. Причём разрабатывают своими силами, а не покупают или адаптируют готовые решения. Вот вам и плацдарм для пробы пера в Пайтоне. Берёте какую-нибудь задачу, которую нужно решить - расписание занятий на сайт или мобильное приложение для студентов или ещё что-нибудь. Получаете добро на разработку у начальства. И вперёд. Через год-другой у вас и строчка в трудовой и реальный опыт и есть, что рассказать на собеседовании. ;)
    Хитрость состоит в том, что в бюджетных организациях часто довольно низкие зарплаты по сравнению с коммерческими фирмами. Поэтому там всегда дефицит кадров и берут они программистов не особенно сильно придираясь. И текучка кадров там приличная. Как только молодёжь приобретает достаточно опыта, она сваливает в коммерческие фирмы, где платят больше. Всё это касается конечно провинции, в столицах, возможно, всё по-другому.
    Ответ написан
    Комментировать