Malley
@Malley

Почему код перестает работать при импорте?

Есть данный код :

import requests
import sqlite3


from . import core_calculation

import data.data_path

YourSecretAPIKey = data.data_path.apis_key
path = data.data_path.path_sql

def get_app_ids(game):

    if game == 'ALL':
        return ['730', '570', '252490', '440']
    elif game == 'CSGO':
        return ['730']
    elif game == 'DOTA':
        return ['570']
    elif game == 'RUST':
        return ['252490']
    elif game == 'TF':
        return ['440']

def create_name_id_cache(AppID):

    conn = sqlite3.connect(path)
    cursor = conn.cursor()

    cursor.execute(f"SELECT DISTINCT nameID FROM parserS WHERE game = {AppID}", )
    name_id_rows = cursor.fetchall()

    name_id_cache = set(row[0] for row in name_id_rows)

    conn.close()

    return name_id_cache




def process_request(AppID):

    url = f'https://api.steamapis.com/market/items/{AppID}?api_key={YourSecretAPIKey}'
    print(url)
    response = requests.get(url)
    print(response)
    if response.ok:
        data = response.json()

        total_items = len(data['data'])
        print(total_items)

        print(1)
        name_id_cache = create_name_id_cache(int(AppID))
        print(2)

        conn = sqlite3.connect(path)
        cursor = conn.cursor()

        update_sql = (
            "UPDATE parserS SET name=?, latest=?, safe=?, safe_ts=?, sold=?, "
            "unstable_reason=?, updated_at=?, avg=?, mean=?, median=?, final_price=?, "
            "sold_seven=?, game=? WHERE nameID=?"
        )

        insert_sql = (
            "INSERT INTO parserS (nameID, name, latest, safe, safe_ts, sold, "
            "unstable_reason, updated_at, avg, mean, median, final_price, sold_seven, game) "
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        )

        values_to_update = []
        values_to_insert = []

        for item in data['data']:

            name_id = item['nameID']
            market_hash_name = item['market_hash_name']
            price_latest = item['prices']['latest']
            price_safe = item['prices']['safe']
            avg = item['prices']['avg']
            mean = item['prices']['mean']
            median = item['prices']['median']
            safe_ts_dict = item['prices']['safe_ts']
            final_price = core_calculation.average_safe_apis(safe_ts_dict)
            sold_data_dict = item['prices']['sold']
            unstable_reason = item['prices']['unstable_reason']
            updated_at = item['updated_at']
            sold_seven = sold_data_dict['last_7d']

            if name_id is None:
                continue

            if int(name_id) in name_id_cache:

                values_to_update.append((
                    market_hash_name, price_latest, price_safe, str(safe_ts_dict),
                    str(sold_data_dict), unstable_reason, updated_at, avg, mean,
                    median, final_price, sold_seven, AppID, name_id
                ))
            else:

                values_to_insert.append((
                    name_id, market_hash_name, price_latest, price_safe,
                    str(safe_ts_dict), str(sold_data_dict), unstable_reason, updated_at,
                    avg, mean, median, final_price, sold_seven, AppID
                ))



        cursor.executemany(update_sql, values_to_update)

        if values_to_insert:
            cursor.executemany(insert_sql, values_to_insert)

        conn.commit()
        conn.close()


    else:
        print('ERROR', response.text)


def update_items_apis(game):

    print('Обновление базы данных стим ...')
    print()

    request_data_list = get_app_ids(game)
    print(request_data_list)
    for AppID in request_data_list:
        print(AppID)
        process_request(AppID)

    print('База данных Steam успешно обновлена!')
    print()


Он прекрасно работает , когда я запускаю только его.

Однако при внедрении этого кода в этот код :

import threading
import time

import core

import support_package.color_out_text

stop_threads = False

dict_block = {'block' : 0}
def continuous_function():

    tt = 0
    ff = 0

    while not stop_threads:

        if dict_block['block'] == 0:

            time.sleep(1)
            tt += 1
            ff += 1
            if ff == 60:

                core.sixtin()
                support_package.color_out_text.color_text('P','60 cекунд')


                ff = 0
            if tt == 300:

                core.three_hundred()

                support_package.color_out_text.color_text('P','300 cекунд')


                tt = 0



def console_function():

    global stop_threads

    support_package.color_out_text.color_text('G','Запуск.')

    while True:
        command = input()
        if command == 'exit':
            stop_threads = True  # Signal threads to stop
            break

        if command == 'buy_items':

            dict_block['block'] = 1
            core.update_items_apis('ALL')
            dict_block['block'] = 0

        else:
            print(f"Running command: {command}")


continuous_thread = threading.Thread(target=continuous_function)
console_thread = threading.Thread(target=console_function)

continuous_thread.start()
console_thread.start()

console_thread.join()

support_package.color_out_text.color_text('G',"Выход.")


При вводе команды buy_items код по сути перестает работать. Даже ответ от get request приходит значительно дольше , а после код и вовсе зависает на
cursor.execute(f"SELECT DISTINCT nameID FROM parserS WHERE game = {AppID}", )
name_id_rows = cursor.fetchall()


В чем вообще может быть проблема? Почему при запуске из основной программы возникают такие трудности?
  • Вопрос задан
  • 167 просмотров
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
sqlite не поддерживает толком одновременную работу в нескольких потоках.

1. У тебя парсер? Перепиши код на асинхронный, тебе не сдалось на самом деле использовать потоки. Они 90% времени будут спать и ждать сетевого ответа. Асинхронный код выполняется в одном потоке, так что таких проблем не будет.
2. Создай отдельный поток, который будет заниматься только работой с базой, и общаться с остальными через какое-то api, например, кладём запрос, данные и какой-то id в очередь, потом читаем ответ из словаря. Но ты по факту будешь писать свой кривенький СУБД-сервер, так что...
3. Вместо sqlite используй любую полноценную СУБД, которая умеет параллельные соединения. Postrge, mariadb, что угодно.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы