• Какой сервер выбрать на 300 пользователей 1с?

    @full_stack_newbie
    Количество пользователей, принципиально, погоды не делает, надо смотреть на интенсивность использования баз.
    Условно 100 документов в час и 1000 документов в час это более весомый аргумент чем 10 или 100 пользователей.
    Субъективно и текущего сервера хватит, только уйти на nvme или ssd. Ну и возможно отказаться от виртуализации, т.к baremetal будет пусть немного, но быстрее. Если его не хватает по производительности - искать причину, анализировать каждую из баз, что там происходит.
    Ответ написан
    7 комментариев
  • Как сохранить порядок ключей в JSONField Django?

    @Everything_is_bad
    Перестаньте уже хранить порядок ключей в dict (хотелка такого с большой вероятностью проблема в архитектуре), хотите порядок положите ключ-значение в list (а не в OrderedDict, у тебя всё таки json, либо писать сериализатор для json)
    Ответ написан
  • Генератор случайных чисел ИНОГДА (очень редко!) возвращает NaN?

    adeshere
    @adeshere Автор вопроса
    РАН, Фортран, временные ряды
    Спустя полтора года, завеса тайны все-таки начала спадать!
    Во-первых, благодаря вот этому совету Дмитрия Чернова, баг удалось локализовать. А именно, Дмитрий предположил, что проблему надо искать в контексте x87 FPU, и что добавление
    пары asm- команд
    Прямую вставку asm- команд в код мой фортран-компилятор не умеет, но все необходимое делает ключ Qfp-stack-check
    в подозрительных местах приведет к вылету программы по Access Violation именно в том месте, где что-то пошло не так. А не спустя какое-то время, когда я снова полезу в FPU и получу Nan, например, в ГСЧ. Эта идея сработала, и я получил Access Violation в совершенно безопасной (как мне казалось)
    функции
    SUBROUTINE SCREEN_PUTL0_TIME(TEXT)
    USE ABD_INC;  USE HEADERS
    character, intent(in) :: text*(*)
    integer*4, save :: isw=0
    c
    c     При самом первом вызове таймера isw=0, функция вернет 0
    c     При последующих (isw=1) - вернет интервал от момента инициализации
    t=timer_mm(5,isw) 
    isw=1
    if (t < $Screen_counter_time) return
    c    В крайнем  случае (если в момент начала внешнего цикла таймер уже
    c    инициализирован) функция первый раз напечатает % сразу при старте,
    c    а не через $Screen_counter_time после запуска цикла
    c   
       call screen_putl0(text)
       t=timer_mm(5,0)         ! Реинициализация таймера после печати строки
    end

    Эта функция печатает на экран % выполнения (он передается в строке TEXT), но с интервалом не менее $Screen_counter_time. Для проверки времени, прошедшего с прошлой печати, вызывается самодельный таймер t=timer_mm(5,isw) Первый параметр функции - это номер таймера (их там у меня целый массив для разных нужд). А второй параметр работает так: если isw=0, то таймер засекает время, а в остальных случаях возвращает число секунд, прошедших с момента инициализации счетчика. Ну вот так было когда-то сделано, чтобы обойтись одной функцией вместо двух....
    Таким образом, когда я дергаю инициализацию таймера, то его возвращаемое значение меня не интересует. Именно это и происходит в предпоследней строке кода выше:
    t=timer_mm(5,0)
    Результат выполнения функции как бы присваивается переменной t, но больше она нигде не используется . Как оказалось, именно здесь и была зарыта собака.

    А дальше уже было проще. В коде под спойлером у меня есть вызов функции типа real*4, от которого мне был нужен только побочный эффект (инициализация таймера), а вот возвращаемое значение функции нигде не используется. В принципе,
    это легально
    По идее, компилятор в такой ситуации должен после вызова функции восстановить стек x87 FPU, а возвращаемое значение никуда не копировать. В других местах кода у меня есть аналогичные вызовы (когда возвращаемое значение не используется), и это не приводит к каким-то багам. Ну и язык официально нигде не требует, чтобы возвращаемое значение функции обязательно было куда-то использовано ;-)

    Но как оказалось, именно это и провоцировало проблему. Этот фрагмент библиотеки у меня состоит из кучи очень небольших (5-10 строк) взаимосвязанных функций с частично повторяющимся кодом. Оптимизатор делал из них жуткое спагетти, дробя эти функции на еще более мелкие фрагменты и инлайня их направо и налево. И, видимо, где-то в ходе этих оптимизаций он "забывал" восстановить (очистить?) стек FPU.

    В общем, для исправления бага оказалось достаточно заменить локальную переменную t на глобальную. Про нее оптимизатор не знает - будет ли она нужна, или нет. Поэтому он просто вынужден извлекать из сопроцессора результат FP-вычисления, чтобы запихнуть его в это место ;-)

    Огромное спасибо Дмитрию, который сначала выдвинул правильную версию происхождения бага, а потом помог его точно локализовать и убрать! Тестовая программа работает уже час и пока ни одного Nan-а не появилось. ;-)
    Ответ написан
    Комментировать
  • При запауске скрипта пишет None, что делать?

    Python_py
    @Python_py
    Смотри, bs4 умеет парсить далеко не все сайты, так как он, по идеи, сдирает каркас (html) структуру, не обращая внимания на те же js скрипты. Скорее с twitch проблема того же рода.
    Для сайтов подобного типа сам использовал Selenium , который может дождаться выполнения js скриптов, а потом уже и снимать нужный сайт.
    Но насколько я помню у некоторых сайтов есть защита от парсинга так что результат не гарантирован.
    А вообще тема распространённая так что советовал бы ознакомиться
    Ответ написан
    Комментировать
  • Не определяется GyverPortal: 'GP' was not declared in this scope; did you mean 'GPC'?

    AlexGyver
    @AlexGyver
    точка с запятой пропущена, в примере они везде стоят после макросов
    Скриншот фрагмента кода удалён модератором.
    И ещё дальше по коду не хватает, ищите :)
    Ответ написан
    1 комментарий
  • Как задать свой тип?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    Создайте его
    https://www.postgresql.org/docs/current/sql-create...
    используйте
    CREATE TYPE contenttype AS ENUM ('FILM', 'SERIAL', 'TRAILER');


    https://www.postgresql.org/docs/current/datatype-e...
    Ответ написан
    Комментировать
  • Как суммировать количество повторяющих значений?

    rozhnev
    @rozhnev
    Fullstack programmer, DBA, медленно, дорого
    WINDOW FUNCTIONS в PostgreSQL уже давно:
    select
        t.*,
        count(*) over (partition by number_id)
    from t order by id;


    https://sqlize.online/sql/psql13/3d37b9a0fe32505b9...
    Ответ написан
    Комментировать
  • Как в SQLITE вывести все строки содержащие определённые слова, независимо от их расположения?

    ThunderCat
    @ThunderCat
    {PHP, MySql, HTML, JS, CSS} developer
    SELECT * 
    FROM persons 
    WHERE name LIKE '%Макаров%' 
    AND name LIKE '%Владимир%' 
    AND name LIKE '%Сергеевич%'
    Ответ написан
    Комментировать
  • Нормально ли учить Django более полугода?

    @12rbah
    Нормально
    Ответ написан
    Комментировать
  • В чем заключаются архитектурные ошибки моего кода?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    class Calculation():
    
      def __init__(self, calculation):
        #init
        self.calculation = calculation

    Вы сделали класс `Вычисления`, чтобы проводить вычисления, пока проводятся вычисления вычислений над вычислениями, которые вычисляются как аргумент вычислений для вычисления состояния вычислений.

    Вы бы хотя бы в предметную область нас тут погрузили хоть немножечку. Не понятно же ничерта. Обычно класс и инстанс можно называть одинаково, за исключением первой буквы, но вы тут в аргументы что-то передаёте и то нифига не понятно. Делайте докстринги.

    Используйте тайпхинтинг, это позволяет не только статичесий анализ кода делать и избегать лишних ошибок, но, к тому же, это мощный инструмент документирования кода, неотрывно связанный с самим кодом. Это значит, что документация не отстанет от кода, а, напротив, будет за счет формализма и машиночитаемости помогать IDE помогать нам писать код. К тому же ряд вопросов отпадёт у тех, кто пытается читать код. Не нужно гадать на кофейной гуще что есть что.

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

    У вас в коде полно "магических" констант. Именуйте их и выносите в начало модуля или, хотя бы, указывайте в инлайн-комментах единицы измерения для ясности. Не пренебрегайте свойствами, их можно документировать .

    Вы тут много работаете с календарными периодами. перебираете их с шагом... Это хорошее место для выделения функциональности в отдельную библиотеку, в отдельный тип данных. Возможно писать свой велосипед даже не придётся, ведь найдётся много готовых качественных протестированных библиотека для этих целей. Их будет легко и понятно инициализировать, у них будет простой, понятный и универсальный АПИ, они будут однотипно использованы в разных мемтах проекта, не придётся смешивать в одном контесте кучу переменных для обеспечения двух имплементаций одной и той же функциональности.
    Количество кода резко убавится, универсальный код будет вынесен в отдельный модуль и будет отдельно и полноценно протестирован, а в бизнес логике вы будете коротко и лаконично работать с абстракцией - понятной и простой.

    Вот тут у вас, очевидно, можно написать проще и без лишних повторений, провоцирующих ошибки:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i not in range(0, self.inflation_indexation_period):
              init_indexation_inflation *= self.sales_init.inflation_indexation
            else:
              init_indexation_inflation = 1
            inflation_indexations.append(round(init_indexation_inflation, 5))
          else:
            inflation_indexations.append(round(init_indexation_inflation, 5))

    Лучше так:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i in range(self.inflation_indexation_period):
              init_indexation_inflation = 1
            else:
              init_indexation_inflation *= self.sales_init.inflation_indexation
    
          inflation_indexations.append(round(init_indexation_inflation, 5))

    Функция get_inflation_indexations у вас имеет опасный побочный эффект. Она имеет префикс get_ но модифицирует контекст объекта. Это кэширование? Чем обусловлено такое поведение? Если такое делается "на всякий случай". то это плохая практика неявного внедрения побочного эффекта. Если нарочно, то такое надо документировать и корректно называть и описывать метод в докстринге.

    Опять же, get_inflation_indexations и get_value_indexations очень похожи по коду. Это повод вынести такую логику в отельную функцию, она будет проще и её будет проще тестировать!
    А у вас эти функции отличаются именами атрибутов внутри и магическими константами, которые в коде делать не хорошо, тем более без пояснений, тем более в кусках такого похожего кода.

    Перестаньте использовать i в качестве переменной для итерирования нетривиальных сущностей, отличных от протсого счетчика. i - это индекс. Используйте человеко-понятное название переменной для этого!

    Используйте декоратор итераторов enumerate. Это сделает код более прозрачным и читабельным, чем код с параллельными счетчиками. Увидев enumerate читатель кода сразу поймёт, что это простой счетчик итерируемых сущностей, что не нужно ожидать скачков этого счетчика и каких-то сложных корреляций.

    А вот здесь вообще всё плохо:
    count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1

    count - это "количество", а вы его используете как "индекс" и никак иначе!
    i - это индекс, а вы туда суёте фактически цену!
    У вас total_price и total_value параллельные одноразмерные списки, их нужно состегнуть с помощью zip и пронумеровать с помощью enumerate (если надо, а здесь не надо!).
    Весь этот кусок понятнее, проще, короче и более питоничнее записать в такой форме:
    revenue_list = [price * value for price, value in zip(total_prices, total_values)]


    Итого вся вот эта громоздкая плохо читабельная функция:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        total_price = []
        for i in self.get_inflation_indexations():
          price = self.sales_init.price*i
          total_price.append(price)
    
        total_value = []
        for i in self.get_value_indexations():
          value = self.sales_init.sales_volume*i
          total_value.append(value)
    
        count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1
    
        return revenue_list

    Легко и читабельно для питониста заменяется на вот такую:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        indexations = self.get_inflation_indexations()
    
        init_price = self.sales_init.price
        total_prices = [init_price * x for x in indexations]
    
        init_volume = self.sales_init.volume
        total_values = [init_volume * x for x in indexations]
    
        return [price * value for price, value in zip(total_prices, total_values)]


    И везде не стоит использовать параллельные счетчики, используйте итераторы, распаковку, зипы, енумервторы и функциональный стиль, ведь он сокращает код и делает его проще.

    Что это за ерунда:
    def get_interest_expenses(self):
        '''процентные расходы'''
        interest_expenses_list = []
        return interest_expenses_list


    Зачем много раз считать одно и то же целиком, чтобы взять только очередной кусочек из всего посчитанного?!
    Это вообще бред. Учитесь основам алгоритмизации и не надо программировать на питоне как не на питоне.

    Вот такое вообще жесть: self.get_revenue()[count]
    Отчего не сохранить в промежуточную переменную?!

    В общем, всё плохо.
    Если у вас есть функция, вычисляющая какой-то список, то зачем её вычислять каждый раз, когда вам нужен только один очередной элеиент этого списка, а вы перебираете его целиком?!
    И так много раз везде!
    Тут не архитектура хромает, тут основы алгоритмизации плачут. Тренируйтесь на кошках, сударь, больше решайте алгоритмических задачек. Структурируйте, декомпозируйте.

    Удачи.
    Ответ написан
    3 комментария
  • Как правильно читается данный запрос?

    @Akela_wolf
    Extreme Programmer
    SELECT --выбрать
      c.name as category_id, -- колонку name из c и обозначить её как category_id
      r.id, r.name, r.country_id, p.category_id -- колонки id, name, country_id из p
    FROM -- из
      " . $this->table_name . " p --какой-то таблицы, обозначая её как p
    LEFT JOIN -- соединив её слева
      category c -- с таблицей category (обозначая её как c)
    ON p.category_id = c.id -- по совпадению значений в колонках category_id и id
    WHERE -- накладывая условие
      p.id = ? -- поле id из p равно какому-то значению
    LIMIT 0,1 -- и выбрать одну (первую) запись (а сортировки-то и нет! Какую считать первой?)
    Ответ написан
    Комментировать
  • Можно ли упростить эту конструкцию try-except?

    @o5a
    while True:
      try:
        n = int(input('N = '))
        break
      except ValueError:
        pass
    print(n)
    Ответ написан
    1 комментарий
  • Как наиболее эффективно прочитать и работать с большим csv в Python?

    Dr_Elvis
    @Dr_Elvis Куратор тега Python
    В гугле забанен
    Можно csv в базу данных импортнуть. В том же DBeaver можно просто открыть cvs как базу данных и написать нужный select
    Ответ написан
    1 комментарий
  • Почему постоянно "вылетает" диск из рейд массива на контроллере PERC H710P Mini?

    Zettabyte
    @Zettabyte
    Проф. восстановление данных ▪ Вопрос? См. профиль
    Firmware Version 21.0.2-0001

    Я бы начал отсюда. Эта версия прошивки от мая 2012-го.
    "Стандартный рубеж" в 2 ТБ этот контроллер явно проходит, но всё-таки 10 лет назад и речи не шло о 16 ТБ дисках.
    Попробуйте обновиться до самой последней версии.

    Второй момент уже тоньше. Размер сектора.
    Ваш контроллер точно поддерживает диски с секторами по 512 байт. А вот с 4K - всё-таки вопрос.

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

    ЕМНИП, диски с 512e доходили до 10 ТБ, но это хорошо было бы уточнить по даташитам. Так что если у вас вдруг есть возможность проверить эту идею с помощью других дисков - проверьте (оптимально, если они будут, например, по 12 ТБ).

    Сервис ответил "диск рабочий"

    Вы сами можете проверить диски с помощью Р.тестера: https://rlab.ru/tools/rtester.html
    Можно попробовать в т.ч. и на сервере - если вылезет что-то непотребное, то сопутствующая этому моменту информация может дать пищу для размышлений.
    Размер сектора можно посмотреть там же, как и здоровье остальных дисков, если нужно. Р.тестер, к примеру, умеет показывать SMART для SAS-винчестеров.
    Ответ написан
    1 комментарий
  • Можно ли заряжать макбук зарядкой повышенной мощности?

    @Akela_wolf
    Extreme Programmer
    Мощность блока питания - это максимальная мощность, которую он может выдать. Если подключить к вашему БП (85 Вт) потребителя, который требует 100 Вт - блок питания не справится с такой нагрузкой (как конкретно это проявится - зависит от схемотехники БП)

    Если же к нему подключить 60 Вт (да хоть 5 Вт) - это будет означать только то что БП работает "вполсилы", у него остается запас мощности т.к. не БП определяет сколько он "впихнет" в потребителя, а, наоборот, потребитель определяет сколько он "заберет" у источника питания. Поэтому резерв мощности никогда не может навредить потребителю. Из этого же, кстати, следует что заряжаться макбук быстрее не станет.
    Ответ написан
    4 комментария
  • Обьясните правда ли эти 2 процессоры очень разные по мощности?

    xez
    @xez
    TL Junior Roo
    Процессор - слишком сложная штука для того чтобы делать вывод о его производительности только по количеству ядер и его частоте.
    До пентиума 4, включительно, все было довольно просто: чем больше мегагерц (а потом гигагерц) - тем процессор быстрее. С тех пор прошло уже 20 лет, кстати.
    У Pentium 4EE частота была уже 3.8Ghz и стало как-то понятно, что дальнейшее ее повышение не дает такого сильного прироста к производительности, как и раньше, да и "стоит" значительно дороже. Поэтому производители начали наращивать количество ядер, увеличивать объем кеш-памяти, и, самое главное, улучшать микроархитектуру (микроархитектуру, вобщем-то, они и так всегда улучшали).

    Вот скриншот из AIDA64:
    61c039d0a31d3774198992.png

    Можно заметить, что частоты у процессоров не слишком то коррелируют с их производительностью.

    Поэтому и существуют многочисленные тесты и бенчмарки, по которым можно понять реальную производительность конкретного процессора в конкретной задаче.
    И да, видимо, i5-2500K быстрее чем Athlon II X4 650
    Ответ написан
    Комментировать
  • Можно ли восстановить данные с SSD?

    Zettabyte
    @Zettabyte
    Проф. восстановление данных ▪ Вопрос? См. профиль
    Можно ли восстановить данные с SSD?

    Да, но не самостоятельно.
    Как SATAFIRM 11 отображаются SSD построенные на основе контроллера Phison PS311. Это происходит из-за того, что у диска повреждена микропрограмма.

    Также возможен ремонт таких дисков посредством запуска Preformat (часто с уменьшением объёма), но это как достаточно неразумное занятие в целом (накопитель снова подведёт), так и противопоказанное вам - при ремонте содержимое теряется безвозвратно.

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

    За всем этим нужно обращаться к специалисту с оборудованием и опытом. Если вы в Москве, будем рады помочь, контакты есть у меня в профиле.
    Если нет и пересылка не подходит, то выбирайте специализирующуюся на восстановлении данных компанию поблизости.

    GoodRam CX400

    Отдельно добавлю, что сильно откладывать не стоит. В подобных SSD используется память далеко не самого высокого качества. Через полтора-два месяца без нормального использования диска заряд в её ячейках может начать утекать, после чего все файлы начнут сильнее и сильнее покрываться "дырками". Так что оптимальным вариантом будет заняться этим вопросом в ближайшие недели, максимум - месяц.

    - P.S. -
    Не сообразил добавить это сразу, но ваш ССД - уже третий на Тостере с такой проблемой за последние 10 дней :-/
    Ответ написан
    5 комментариев
  • Как можно сократить этот JQuery код?

    megakor
    @megakor
    Go/PHP developer | Вконтакте
    $(`.pict${i}, .buy${i}`).fadeIn(300);
    Ответ написан
    Комментировать
  • Почему проблема в сортировке?

    Vindicar
    @Vindicar
    RTFM!
    Код феерический. Два запроса вместо одного, выбор всех строк ради сортировки на клиенте, NULL там, где его быть не должно, и так далее.

    Всё это прекрасно делается на уровне запроса к базе!
    SELECT fname, balance FROM users WHERE balance IS NOT NULL ORDER BY balance DESC LIMIT 5

    Выберет имя и баланс пользователей, у которых баланс не NULL (sql-евский NULL превращается в питоновский None, с которым ты и столкнулся при сортировке). Это, к слову, твоя вина, нужно было указать NOT NULL и значение по умолчанию для поля balance при создании таблицы.
    Результат сортируется по полю balance по убыванию, и выбираются не более первых 5 строк (может быть менее).
    Каждая строка результата будет кортежем, где нулевой элемент - имя игрока, а первый - баланс.

    top5 = cur.execute('SELECT fname, balance FROM users WHERE balance IS NOT NULL ORDER BY balance DESC LIMIT 5').fetchall()
    table = []
    for num, (fname, x) in enumerate(top5, 1):
        table.append(f'{num} • {fname} - <b><i>{x}</i></b> монеток.\n' )
    await message.reply('Топ 5 богачей бота.\n\n'+''.join(table))


    Подучи SQL, сильно упростишь себе жизнь при составлении запросов.
    Ответ написан
    Комментировать
  • Как выбрать строки по времени не раньше 30 и не позже 60 минут?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    WHERE `time` BETWEEN NOW() - INTERVAL 60 MINUTE AND NOW() - INTERVAL 30 MINUTE
    Ответ написан
    1 комментарий