Задать вопрос
  • SSH туннель, как получить доступ к приватному компу за нат с сервера на котором поднят туннель?

    trapwalker
    @trapwalker
    Magnoliya, тут нет лички, но ник в телеге такой же. Пишите. Но когда разберетесь со своей проблемой, не забудьте отписаться здесь в чем она заключалась.
  • SSH туннель, как получить доступ к приватному компу за нат с сервера на котором поднят туннель?

    trapwalker
    @trapwalker
    Я написал в точности нужную команду.
    У меня такая же ситуация и всё работает именно так.
    На локальной машине (за натом обычного провайдера - региональные телесистемы) запущен некий веб-интерфейс на 8081 порту.
    Нужно ходить на него из любого места в интернете.
    У меня есть VPS с линуксом и статическим ip. На локальной машине тоже линукс.
    Я подключаюсь с локальной машине по ssh к vps такой же командой, что выше и порт локальной машины пробрасывается через туннель на vps/
    Теперь с любой машины в интернете можно подключаться к порту vps, а фактичеки соединение будет происходить с машиной, которая за натом. Через туннель.
    Что и очему у вас не работает - не понятно, недостаточно информаии, чтобы разобраться в причине проблемы.
    У меня даже нет уверенности, что у вас эта проблема на самом деле есть. Думаю вы просто перепутали что-то, не туда подключаетесь или не так определяете наличие коннекта.

    В моём ответе "192.168.0.10" - это локальный адрес машины, которая за натом. Если в ssh туннель до vps вы поднимаете прямо с нее, то вместо этого адреса можно указать 127.0.0.1. Это локальный интерфейс, он должен быть у каждой машины
  • Литий полимерный аккумулятор и ванная комната?

    trapwalker
    @trapwalker
    Сушить в микроволновке на 800Ваттах до полной прожаоки=)
    Шутка
  • SSH туннель, как получить доступ к приватному компу за нат с сервера на котором поднят туннель?

    trapwalker
    @trapwalker
    Я же вам ссылки дал. там с примерами.
    ssh -f -N -L 4080:192.168.0.10:80 nameuser@88.77.66.55

    192.168.0.10 - адрес машины, которую нужно высунуть портом наружу через vps.
    nameuser@88.77.66.55 - логин и адрес для подключения к впс
    4080 - это порт на впс, к которому будет привязан порт 80 локальной машины.
    То если проброс делается прямо с нее, то айпи локальной машины может быть 127.0.0.1.

    В вашем случае вместо 80 будет ваш порт.
  • Как оптимизировать вставку данных в таблицу с 2млн строк?

    trapwalker
    @trapwalker
    Вопрос нужно конкретизировать:
    - какова логика проверки наличия товара?
    - если он происходит перед вставкой, как она может совпасть с моментом добавления товара?
    - вы делаете это во много потоков, что ли?
    - какие индексы есть в таблице?
    - какие запросы вы делаете при вставке и проверке?
    - какой план генерится для этих запросов?

    Без кода не понять в чем там у вас проблема.
    2 миллиона строк - это не должно быть проблемой, если есть необходимые индексы.
    Порядок вставки (в плане оптимизации) сильно зависит от того, какие и в каком количестве процессы работают с БД одновремено, какие требования и ограничения по консистентности данных, какие размеры пакетов вставляемых данных типичны для рабочего процесса... и т.д.
  • Почему удаляются данные из переменной?

    trapwalker
    @trapwalker Куратор тега Python
    Алан Гибизов, похоже топикстартер таким странным бразом хотел посчитать статистику использования разных почтовых сервисов пользователями.
  • Почему удаляются данные из переменной?

    trapwalker
    @trapwalker Куратор тега Python
    Алан Гибизов, зачем вам ример данных из csv? Что бы там ни было, всё вычитывается при создании словаря. После создания словаря генератор пуст и при распаковке в аргументы для принта список аргументов будет пустым.
  • Как выбрать последнюю строку в которой было определенное слово?

    trapwalker
    @trapwalker Куратор тега Python
    kekekfds, отрежьте их слайсом.
    Вообще этот ваш вопрос выдаёт ваше полное незнание языка. В этом свете ваш вопрос становится заданием, а задания на этм ресурсе запрещены.
    Если хотите освоить язык, начните с любого учебника по питону.
  • Как выбрать последнюю строку в которой было определенное слово?

    trapwalker
    @trapwalker Куратор тега Python
    Зачем же так неэлегантно писать?
    Чуть модифицировать можно код автора:
    last_line = None
    word = u'какое-то слово'
    with open('файл.log', encoding='utf-8') as file:
        for line in file:
            if word in line:
                last_line = line
    
    print(last_line)
  • Данный вопрос уже был, но это другое. Как боту отправить сообщение пользователю, зная его id?

    trapwalker
    @trapwalker
    Lev Frolov, причем тут тех-поддержка?
    Я вижу вашу постановку задачи:
    Когда клиент общается с ботом, бот выдает ему список товаров, когда клиент выбрал товар бот собирает товар и данные клиента ( он ввел их заранее ) и отправляет определённому пользователю (Макс допустим). Предположим Макс уже общался с ботом.

    Я так понял, что роль у Макса не такая же, как у клиента. Вот их я и предложил разделить.
    Вы же ничего о предметной области практически не написали. Может быть у вас клиенты друг другу заказы формируют.
    В любом случае должна быть выделена сущность заказа и сформирована некоторая очередь этих заказов.
    Описаннный вами бизнес-процесс следует разделить на два отдельных подроцесса: 1) приём заказов, 2) обработка заказов.
  • Как правильно настроить многопоточность у бота telegram?

    trapwalker
    @trapwalker Куратор тега Python
    newPsevdonim, чем вас не устроил этот ответ?
    Могу добавить, что посоветовал бы использовать мультипроцессинг. Всё же в питоне потоки не решают проблем, с которыми вы тут столкнулись. Не понятно как именно вы там делаете файловые операции, но напрашивается отдельный воркер в отдельном процессе, который это будет делать по заданию из очереди, как вам предложил Vindicar
  • Почему SQL запрос ничего не возвращает?

    trapwalker
    @trapwalker Куратор тега Python
    newPsevdonim, я вижу кусочек кода и сужу именно по нему.
    В более качественно написанном коде это бросалось бы в глаза сразу и вы не потеряли бы из виду этот нюанс.

    Давайте попробую докопаться до кода детально.
    # Тут не буду писать про форматиование, ниже покажу как лучше 
    # и прозрачнее форматировать такие участки кода
    # Но здесь отмечу, что в питоне есть замечательные f-строки
    # для более читабельной подстановки параметров.
    # Вообще любые позиционные параметры, в отличии от именованных,
    # сегда сильно снижают читабельность, размазывая контекст необходимого внимания
    # по коду.
    last_time = self.client.execute('SELECT time_local FROM {} ORDER'
                                                ' BY time_local DESC LIMIT 1'.format(table_name))
    # Здесь появляется непонятная переменная tag, которая никак не пояснена в вопросе:
    self.last_time[tag] = last_time[0][0]
    print(self.last_time[tag])
    # А вот здесь снова нечитабельные и зачастую опасные позиционные подстановки
    # среди которых ОЧЕНЬ опасное и мусорное экранирование, которое грозит нам 
    # потенциальными SQL-инъекциями.
    # А ещё в контексте вашего кода одно и то же у вас называется 
    # двумя непохожими именами: tag и client_id. Для того, кто будет итать ваш код
    # одинаковые вещи должны называться одинаково. 
    # Это, я считаю, наравне с форматированием, основная причина вашей ошибки тут.
    table = self.client.execute('SELECT {} FROM {} WHERE client_id = \'{}\''
                                            'AND time_local >= \'{}\' ORDER BY'
                                            ' time_local DESC'.format(table_fields,
                                                                      table_name,
                                                                      tag,
                                                                      self.last_time[tag] - timedelta(seconds=5)))

    Давайте отформатируем код и он сразу станет гораздо читабельнее:
    st_time = self.client.execute(f'''
        SELECT time_local 
        FROM {table_name} 
        ORDER BY time_local DESC 
        LIMIT 1
    ''')
    self.last_time[tag] = last_time[0][0]
    print(self.last_time[tag])
    time_5_seconds_ago = self.last_time[tag] - timedelta(seconds=5)
    table = self.client.execute(f'''
        SELECT {table_fields} 
        FROM {table_name} 
        WHERE 
            client_id = {str(tag)!r}
            AND time_local >= {str(time_5_seconds_ago)!r}
        ORDER BY time_local DESC
    ''')

    Строчек получилось чуть больше, но читабельность и прозрачность кода повысилась, хотя код по-прежнему далеко не идеален.
    Не знаю что там за клиентскую библиотеку для работы с БД вы используете, но у всех библиотек есть встроенный механизм передачи и экранирования параметров. Его нужно использовать и это вопрос не только хорошего стиля, но и вопрос безопасности от SQL-инъекций.
    Даже если конкретно здесь инъекция пока невозможна, сам факт того, что у вас уже сформировалась привычка такой передачи параметров в запросы уже делает вас, как программиста, не безопасным.
    А этот код, возможно, будут править другие люди, и они, возможно, захотят добавить ещё какие-нибудь параметры и пробросят их так же, как тут уже сделано, и вот там может случиться что угодно.
    Ваш код, даже если в данном случае конкретно здесь он безопасен, своим форматированием и способом передачи параметров в запрос маскирует потенциально опасные ситуации.

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

    Не принимайте на свой счет мои слова о говнокоде. Все иногда его пишут. Главное воспринимать с пользой конструктивную критику и учиться на ошибках. Иногда наговнокодить - это не стыдно. Стдно делать это изо дня в день и не работать над собой для улучшения навыка.

    Обосновал?
    327_v1.png
    1543162645134063080.jpg
  • Как организовать одновременную работу Telegram бота (Aiogram) и Flask?

    trapwalker
    @trapwalker Куратор тега Python
    Vindicar, да чего там учить? На докерхабе полно докерфайлов в качестве примеров для всего.
    Основная концепция довольно проста, но в плане изоляции эта шутка просто прекрасна.
  • Закрывается ли в таком случае поток и невредно ли так делать?

    trapwalker
    @trapwalker Куратор тега Python
    Сергей Горностаев, важное замечание. Да и глупо, к примеру, на FastAPI делать на тредах такие вещи
  • Как сделать скрипт bash правильно?

    trapwalker
    @trapwalker
    Тоже посоветовал бы на питоне делать. Баш-скрипт такой сложности и размера для особых извращенцев.
    Описанная вами функциональность хорошо ложится на отдельную питоновскую консольную тулзу.
    Её можно положить в гитхаб и открыть для всех, принимать пулл-риквесты.

    Такого рода небольший проекты хороши для тренировки джунов. Можно запросить ревью у кого-то даже тут.
    Но в описанном вами виде это бессмысленно.
    Ну скачает кто-то ваш конский скрипт, ну внесет какие-то правки, это же получится одноразовая история, её не отмасштабировать и количество знания на QNA не увеличится.

    Ваш вопрос здесь не соответствует тематике ресурса. Он не конкретен.
  • Закрывается ли в таком случае поток и невредно ли так делать?

    trapwalker
    @trapwalker Куратор тега Python
    old_stalin, не надо ничего менять. _thread испольузется внутри threading.
    _thread - это враппер вокруг встроенной сишной библиотеки.
    Нет никакого смысла использовать треды на таком низком уровне, когда есть хорошая объектная обертка в виде threading.
  • Закрывается ли в таком случае поток и невредно ли так делать?

    trapwalker
    @trapwalker Куратор тега Python
    old_stalin, тут надо, всё же, послушать доводы Сергей Горностаев, ведь каждый может ошибаться, даже я.=)
  • Закрывается ли в таком случае поток и невредно ли так делать?

    trapwalker
    @trapwalker Куратор тега Python
    old_stalin, почему это не закрытых?
    Вот в исходниках:
    def start_new_thread(function, args, kwargs=None): # real signature unknown; restored from __doc__
        """
        start_new_thread(function, args[, kwargs])
        (start_new() is an obsolete synonym)
        
        Start a new thread and return its identifier.  The thread will call the
        function with positional arguments from the tuple args and keyword arguments
        taken from the optional dictionary kwargs.  The thread exits when the
        function returns; the return value is ignored.  The thread will also exit
        when the function raises an unhandled exception; a stack trace will be
        printed unless the exception is SystemExit.
        """
        pass

    По идее завершение или исключение в функции b() должно останавливать тред.