Skip to content

python ile youtube dan mp3 indirmek

bir çoğumuzun hayatından artık mp3 dosyaları çıktı. artık sevidğimiz müzikleri ya online dinliyoruz yada tercih ettiğimiz bir uygulamanın offline modunu kullanıyoruz.

benim gibi bir kaç mp3 indirmek isteyen çıkabilir.

bunun için reklamlarla dolu video dosya içerisinden ses dosyasını kaydetmenize sağlayan bir sürü site var.. isterseniz bunlardan birini kullanabillirsiniz.. ama ben bunlarla uğraşmak istemediğim için basit bir uygulama yapmak istedim..

kodu tabiki pythonda yazacağız.. kod sırasında bize yardımcı olacak bir çok modül mevcut. bunların bir çoğu ffmpeg kullanıyor ve pc nizde kurulu olmasını şart koşuyor.

bu noktada yt_dlp yardımımıza yetişiyor. denediğim modüller arasında en sağlık çalışanı yt_dlp oldu.

şimdi adresini bildiğimiz bir youttube url için yt_dlp modulunu kullanarak mp3 dosyasını nasıl elde ederiz basit bir örnek yapalım.

import yt_dlp

def muzik_dosyasi_indir(video_url, output_folder="mp3_klasor"):
    options = {
        'format': 'bestaudio/best',
        'outtmpl': f'{output_folder}/%(title)s.%(ext)s',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }],
        'noplaylist': True
    }

    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([video_url])

video_url = "https://www.youtube.com/watch?v=<video_id>"
muzik_dosyasi_indir(video_url, output_folder="mp3_klasor")

temel kodumuz yukarıdaki gibi olacaktır… mp3 olarak indirmek istediğiniz bir video dosyasının idsini koddaki <video_id> ile değiştirir ve kodu çalıştırsanız aşagıdaki gibi çıktı ile çarşılacaksınız.

[youtube] Extracting URL: https://www.youtube.com/watch?v=8umGN3KiGY4
[youtube] 8umGN3KiGY4: Downloading webpage
[youtube] 8umGN3KiGY4: Downloading tv client config
[youtube] 8umGN3KiGY4: Downloading player e7567ecf
[youtube] 8umGN3KiGY4: Downloading tv player API JSON
[youtube] 8umGN3KiGY4: Downloading ios player API JSON
[youtube] 8umGN3KiGY4: Downloading m3u8 information
[info] 8umGN3KiGY4: Downloading 1 format(s): 251
[download] Destination: mp3_klasor\Passenger - Let Her Go.webm
[download] 100% of    4.05MiB in 00:00:00 at 8.79MiB/s
[ExtractAudio] Destination: mp3_klasor\Passenger - Let Her Go.mp3
Deleting original file mp3_klasor\Passenger - Let Her Go.webm (pass -k to keep)

günsan elektrik – tuya destekli akıllı priz

uzaktan kontrol ve zamanlama için bir adet akıllı priz ihtiyacı oldu. bir alış veriş sitesinden kampanyadan faydalanarak günsan elektrik e ait olan prizden sipariş verdim. ürünün resmi sayfası

https://www.gunsanelectric.com/urunler/anahtar-priz/smart/wi-fi-kontrollu-akilli-priz-16a

şeklinde..

yerli ürün alalım diye düşürken içten içe üzerine günsan yazılmış fason olarak üretilmiş bir ürün alaağımı biliyordum. günsan smart life uygulamasını kendisine göre uyarlamış ama eksiklerde kalmış.. bazı yerlerde hala smartlife yazıyor 🙂

günsanın gg smart isimli uygulamasını kullanarak kısa sürede ürünü uygulamaya sorunsuz olarak ekleyebiliyorsunuz. tuya veya smart life uygulamasını kullanmak istersenizde sorun yaşamıyorsunuz.

buraya kadar sorun yok ancak sizde benim gibi uygulamalarda istediğinizi yapamıyorsanız, verilerinizi dış dünya ile paylaşmak istemiyor ve olası güvenlik açıklarının önüne geçmek istiyebilirsiniz.

bunun için kendi uygulamamızı yazabiliriz veya evinizde çalıştırdığınız bir akıllı ev asistanına ekleyebilirsiniz. ancak bunu yapabilmeniz için cihazın iletşim prokolu vb bilgileri gerekli. bu bilgiler ne yazıkkı cihaz ile doğrudan size gelmiyor.

adım adım bu bilgileri nasıl elde edeceğimize ve nasıl basit bir program yazacağımıza bakalım.

öncelikle akıllı prizinize smart life uygulamasına doğru şekilde ekleyin.

akıllı priz wifi desteğine sahip olduğu için ipsini öğrenmeliyiz. bunu ağınızda ip taraması veya modem arayüzünden rahatlıkla bulabilirsiniz. sonrasına bir port scanner ile açık olan portları bulmalıyız… bu ürün 6666, 6667, 6668 portlarını kullanıyor.

ihtiyacımız olan diğer bilgilere ulaşmanın bir kaç yöntemi var.

en temel haliyle yakadığımız pakeleri analiz ederek bu verilere ulaşabiliriz.. mitm, proy , wireshak vb ile uğraşmayı seviyersanız konuya zaten hekimsinizdir burada anlatmayacağım, siz hallederseniz. biz daha basit olan yöntemlere bakalım.

tuya geliştirici ortamı üzerinden nasıl öğreneceğimizi inceleyelim. öncelikle

https://developer.tuya.com/en

adresinden kendimize bir hesap oluşturalım. hesap oluşumunda sonra

https://platform.tuya.com/cloud

adresinden bir proje oluşturalım.. proje oluştururken aşagıdaki parametreleri kullanabilirsiniz. dikkat etmeniz gereken nokta data center seçimi olacak. ileleyen aşamalarda yapacağımız bazı işlemlerde seçtiğiniz data center önem kazanıyor.. US veya Central Europe seçmenizi öneririm..

sonrasında kullanacağınız api servislerini belirlemeniz gerekiyor. Smart Home Content Manage, [Deprecate]Device Log Query , Smart Home Basic Service, [Deprecate]Smart Home Scene Linkage servislerinin seçili olması olmasına dikkat edelim.

projeyi oluşturduktan sonra aşagıdaki gibi ekran bizi karşılayacaktır.

Device altına giriyoruz

sonrasında Link App Account a seçip Add App Account butonuna tıklıyoruz. açılan penceredki qr kodu

smart life uygulamasında tanımlama kısmında taratacağız. bu işlem başarılı olarak tamamlandıktan sonra smart life uygulamasına eklediğiniz tuya destekli cihazları platformda görmeye başlayacaksınız

Device Permission ayarlarını Controllable olarak ayarlayın.. buraya kadar yaptıklarımız sayesinde tuya developer üzerinden akıllı prizlerimizi kontrol edebilir ve izleyebilir duruma getirmiş olduk.

şimdi api explorer i açalım.

https://platform.tuya.com/cloud/explorer

platformu açtıktan sonra “query device details” sorgusu altında device list altında gördüğümüz device id bilgisini girerek

sorguyu çalıştırdığımızda aşagıdaki gibi bir sonuç elde ediyoruz. product id ve model bilgisinden ürünün bir fason olduğunu görüyoruz.

{
  "result": {
    "active_time": 1738437687,
    "bind_space_id": "223209011",
    "category": "cz",
    "create_time": 1738180007,
    "custom_name": "tv",
    "icon": "smart/icon/ay1544008322541hl9iQ/9aebc86a6392f0b9495d826cba17ba54.jpg",
    "id": "xxxxxxxxxxxxxxxxxxxx",
    "ip": "11.11.11.11",
    "is_online": true,
    "lat": "38.74",
    "local_key": "xxxxxxxxxxxxxxxxxxxx",
    "lon": "35.44",
    "model": "EU02A-中性欧规EU02A-16A计量CB2S-BK7231N 过充保护",
    "name": "Smart plug 2",
    "product_id": "newhgkiotowsaryi",
    "product_name": "Smart Plug",
    "sub": false,
    "time_zone": "+03:00",
    "update_time": 1738437697,
    "uuid": "xxxxxxxxxxxxxxxxxxxx"
  },
  "success": true,
  "t": 1738528737555,
  "tid": "xxxxxxxxxxxxxxxxxxxx"
}

elde ettiğimiz bu bilgilerle lokalden akıllı prize bağlanıp veri çekebiliriz.

Alacağımız veriler bize doğrudan bir şey ifade etmeyebilir. anlamlı hale getirmek için Query Things Data Model altından data modelini elde edelim.

elde edilen çıktı aşagıdaki şekildedir…

{
  "result": {
    "model": "{\"modelId\":\"000004yex6\",\"services\":[{\"actions\":[],\"code\":\"\",\"description\":\"\",\"events\":[],\"name\":\"默认服务\",\"properties\":[{\"abilityId\":1,\"accessMode\":\"rw\",\"code\":\"switch_1\",\"description\":\"\",\"extensions\":{\"iconName\":\"icon-dp_power2\",\"attribute\":\"641\"},\"name\":\"开关1\",\"typeSpec\":{\"type\":\"bool\"}},{\"abilityId\":9,\"accessMode\":\"rw\",\"code\":\"countdown_1\",\"description\":\"\",\"extensions\":{\"iconName\":\"icon-dp_time2\",\"attribute\":\"736\"},\"name\":\"开关1倒计时\",\"typeSpec\":{\"type\":\"value\",\"max\":86400,\"min\":0,\"scale\":0,\"step\":1,\"unit\":\"s\"}},{\"abilityId\":17,\"accessMode\":\"ro\",\"code\":\"add_ele\",\"description\":\"\",\"extensions\":{\"attribute\":\"704\"},\"name\":\"增加电量\",\"typeSpec\":{\"type\":\"value\",\"max\":50000,\"min\":0,\"scale\":3,\"step\":100}},{\"abilityId\":18,\"accessMode\":\"ro\",\"code\":\"cur_current\",\"description\":\"\",\"extensions\":{\"attribute\":\"704\"},\"name\":\"当前电流\",\"typeSpec\":{\"type\":\"value\",\"max\":30000,\"min\":0,\"scale\":0,\"step\":1,\"unit\":\"mA\"}},{\"abilityId\":19,\"accessMode\":\"ro\",\"code\":\"cur_power\",\"description\":\"\",\"extensions\":{\"attribute\":\"704\"},\"name\":\"当前功率\",\"typeSpec\":{\"type\":\"value\",\"max\":80000,\"min\":0,\"scale\":1,\"step\":1,\"unit\":\"W\"}},{\"abilityId\":20,\"accessMode\":\"ro\",\"code\":\"cur_voltage\",\"description\":\"\",\"extensions\":{\"attribute\":\"704\"},\"name\":\"当前电压\",\"typeSpec\":{\"type\":\"value\",\"max\":5000,\"min\":0,\"scale\":1,\"step\":1,\"unit\":\"V\"}},{\"abilityId\":21,\"accessMode\":\"ro\",\"code\":\"test_bit\",\"description\":\"\",\"extensions\":{\"attribute\":\"736\"},\"name\":\"产测结果位\",\"typeSpec\":{\"type\":\"value\",\"max\":5,\"min\":0,\"scale\":0,\"step\":1}},{\"abilityId\":22,\"accessMode\":\"ro\",\"code\":\"voltage_coe\",\"description\":\"\",\"extensions\":{\"attribute\":\"736\"},\"name\":\"电压校准系数\",\"typeSpec\":{\"type\":\"value\",\"max\":1000000,\"min\":0,\"scale\":0,\"step\":1}},{\"abilityId\":23,\"accessMode\":\"ro\",\"code\":\"electric_coe\",\"description\":\"\",\"extensions\":{\"attribute\":\"736\"},\"name\":\"电流校准系数\",\"typeSpec\":{\"type\":\"value\",\"max\":1000000,\"min\":0,\"scale\":0,\"step\":1}},{\"abilityId\":24,\"accessMode\":\"ro\",\"code\":\"power_coe\",\"description\":\"\",\"extensions\":{\"attribute\":\"736\"},\"name\":\"功率校准系数\",\"typeSpec\":{\"type\":\"value\",\"max\":1000000,\"min\":0,\"scale\":0,\"step\":1}},{\"abilityId\":25,\"accessMode\":\"ro\",\"code\":\"electricity_coe\",\"description\":\"\",\"extensions\":{\"attribute\":\"736\"},\"name\":\"电量校准系数\",\"typeSpec\":{\"type\":\"value\",\"max\":1000000,\"min\":0,\"scale\":0,\"step\":1}},{\"abilityId\":26,\"accessMode\":\"ro\",\"code\":\"fault\",\"description\":\"\",\"extensions\":{\"attribute\":\"640\"},\"name\":\"故障告警\",\"typeSpec\":{\"type\":\"bitmap\",\"label\":[\"ov_cr\",\"ov_vol\",\"ov_pwr\",\"ls_cr\",\"ls_vol\",\"ls_pow\"],\"maxlen\":6}},{\"abilityId\":38,\"accessMode\":\"rw\",\"code\":\"relay_status\",\"description\":\"\",\"extensions\":{\"iconName\":\"icon-zhuangtai\",\"attribute\":\"736\"},\"name\":\"上电状态设置\",\"typeSpec\":{\"type\":\"enum\",\"range\":[\"off\",\"on\",\"memory\"]}},{\"abilityId\":39,\"accessMode\":\"rw\",\"code\":\"overcharge_switch\",\"description\":\"\",\"extensions\":{\"attribute\":\"128\"},\"name\":\"过充保护\",\"typeSpec\":{\"type\":\"bool\"}},{\"abilityId\":40,\"accessMode\":\"rw\",\"code\":\"light_mode\",\"description\":\"\",\"extensions\":{\"iconName\":\"tcl_function_light\",\"attribute\":\"224\"},\"name\":\"指示灯状态设置\",\"typeSpec\":{\"type\":\"enum\",\"range\":[\"relay\",\"pos\",\"none\",\"on\"]}},{\"abilityId\":41,\"accessMode\":\"rw\",\"code\":\"child_lock\",\"description\":\"\",\"extensions\":{\"iconName\":\"icon-dp_power2\",\"attribute\":\"128\"},\"name\":\"童锁开关\",\"typeSpec\":{\"type\":\"bool\"}},{\"abilityId\":42,\"accessMode\":\"rw\",\"code\":\"cycle_time\",\"description\":\"涂鸦协议\",\"extensions\":{\"iconName\":\"icon-dp_time3\",\"attribute\":\"224\"},\"name\":\"循环定时\",\"typeSpec\":{\"type\":\"string\",\"maxlen\":255}},{\"abilityId\":43,\"accessMode\":\"rw\",\"code\":\"random_time\",\"description\":\"涂鸦协议\",\"extensions\":{\"iconName\":\"icon-dp_time2\",\"attribute\":\"224\"},\"name\":\"随机定时\",\"typeSpec\":{\"type\":\"string\",\"maxlen\":255}},{\"abilityId\":44,\"accessMode\":\"rw\",\"code\":\"switch_inching\",\"description\":\"涂鸦协议\",\"extensions\":{\"attribute\":\"224\"},\"name\":\"点动开关\",\"typeSpec\":{\"type\":\"string\",\"maxlen\":255}}]}]}"
  },
  "success": true,
  "t": 1738532745188,
  "tid": "0e8bf1f9e1af11ef9e609e9247cde4aa"
}

görüleceği üzere açıklamalar vb çince.. bunu python altında kullanmak için anlamlı hale getirelim.

# DPS tanımları
DPS_MAPPING = {
    '1': {
        'id': 1,
        'name': 'Güç Anahtarı',
        'code': 'switch_1',
        'type': bool,
        'access': 'rw',
        'icon': 'icon-dp_power2',
        'format': lambda x: 'Açık' if x else 'Kapalı'
    },
    '9': {
        'id': 9,
        'name': 'Geri Sayım',
        'code': 'countdown_1',
        'type': int,
        'access': 'rw',
        'icon': 'icon-dp_time2',
        'max': 86400,
        'min': 0,
        'scale': 0,
        'step': 1,
        'unit': 'saniye',
        'format': lambda x: f'{x} saniye'
    },
    '17': {
        'id': 17,
        'name': 'Toplam Enerji',
        'code': 'add_ele',
        'type': int,
        'access': 'ro',
        'max': 50000,
        'min': 0,
        'scale': 3,
        'step': 100,
        'format': lambda x: f'{x/1000:.3f} kWh'
    },
    '18': {
        'id': 18,
        'name': 'Anlık Akım',
        'code': 'cur_current',
        'type': int,
        'access': 'ro',
        'max': 30000,
        'min': 0,
        'unit': 'mA',
        'format': lambda x: f'{x/1000:.2f} A'
    },
    '19': {
        'id': 19,
        'name': 'Anlık Güç',
        'code': 'cur_power',
        'type': int,
        'access': 'ro',
        'max': 80000,
        'min': 0,
        'scale': 1,
        'unit': 'W',
        'format': lambda x: f'{x/10:.1f} W'
    },
    '20': {
        'id': 20,
        'name': 'Anlık Voltaj',
        'code': 'cur_voltage',
        'type': int,
        'access': 'ro',
        'max': 5000,
        'min': 0,
        'scale': 1,
        'unit': 'V',
        'format': lambda x: f'{x/10:.1f} V'
    },
    '21': {
        'id': 21,
        'name': 'Test Sonucu',
        'code': 'test_bit',
        'type': int,
        'access': 'ro',
        'max': 5,
        'min': 0,
        'format': lambda x: f'Test Sonucu: {x}'
    },
    '26': {
        'id': 26,
        'name': 'Hata Durumu',
        'code': 'fault',
        'type': int,
        'access': 'ro',
        'labels': ['Aşırı Akım', 'Aşırı Voltaj', 'Aşırı Güç', 'Düşük Akım', 'Düşük Voltaj', 'Düşük Güç'],
        'format': lambda x: decode_fault(x)
    },
    '38': {
        'id': 38,
        'name': 'Röle Durumu',
        'code': 'relay_status',
        'type': str,
        'access': 'rw',
        'icon': 'icon-zhuangtai',
        'range': ['off', 'on', 'memory'],
        'format': lambda x: {'off': 'Kapalı', 'on': 'Açık', 'memory': 'Hafıza'}.get(x, x)
    },
    '39': {
        'id': 39,
        'name': 'Aşırı Şarj Koruması',
        'code': 'overcharge_switch',
        'type': bool,
        'access': 'rw',
        'format': lambda x: 'Aktif' if x else 'Pasif'
    },
    '40': {
        'id': 40,
        'name': 'LED Gösterge Modu',
        'code': 'light_mode',
        'type': str,
        'access': 'rw',
        'icon': 'tcl_function_light',
        'range': ['relay', 'pos', 'none', 'on'],
        'format': lambda x: {'relay': 'Röle', 'pos': 'Pozisyon', 'none': 'Kapalı', 'on': 'Açık'}.get(x, x)
    },
    '41': {
        'id': 41,
        'name': 'Çocuk Kilidi',
        'code': 'child_lock',
        'type': bool,
        'access': 'rw',
        'icon': 'icon-dp_power2',
        'format': lambda x: 'Kilitli' if x else 'Kilitsiz'
    },
    '42': {
        'id': 42,
        'name': 'Döngü Zamanlayıcı',
        'code': 'cycle_time',
        'type': str,
        'access': 'rw',
        'icon': 'icon-dp_time3',
        'maxlen': 255,
        'format': lambda x: f'Döngü: {x}'
    },
    '43': {
        'id': 43,
        'name': 'Rastgele Zamanlayıcı',
        'code': 'random_time',
        'type': str,
        'access': 'rw',
        'icon': 'icon-dp_time2',
        'maxlen': 255,
        'format': lambda x: f'Rastgele: {x}'
    },
    '44': {
        'id': 44,
        'name': 'Anlık Anahtar',
        'code': 'switch_inching',
        'type': str,
        'access': 'rw',
        'maxlen': 255,
        'format': lambda x: f'Anlık: {x}'
    }
}

def decode_fault(fault_code):
    faults = []
    fault_map = {
        0: "Aşırı Akım",
        1: "Aşırı Voltaj", 
        2: "Aşırı Güç",
        3: "Düşük Akım",
        4: "Düşük Voltaj",
        5: "Düşük Güç"
    }
    
    for bit, fault in fault_map.items():
        if fault_code & (1 << bit):
            faults.append(fault)
    
    return ', '.join(faults) if faults else 'Normal'

şimdi tinyyuya modulunu kullanarak akıllı prizimiden veri çekecek python kodumuzu yazalım…

import tinytuya
import time

# Cihaz bilgileri
DEVICE_ID = "xx"
IP_ADDRESS = "192.168.1.143"
LOCAL_KEY = "xx"
VERSION = 3.4

# DPS tanımları
DPS_MAPPING = {
    '1': {
        'id': 1,
        'name': 'Güç Anahtarı',
        'code': 'switch_1',
        'type': bool,
        'access': 'rw',
        'icon': 'icon-dp_power2',
        'format': lambda x: 'Açık' if x else 'Kapalı'
    },
    '9': {
        'id': 9,
        'name': 'Geri Sayım',
        'code': 'countdown_1',
        'type': int,
        'access': 'rw',
        'icon': 'icon-dp_time2',
        'max': 86400,
        'min': 0,
        'scale': 0,
        'step': 1,
        'unit': 'saniye',
        'format': lambda x: f'{x} saniye'
    },
    '17': {
        'id': 17,
        'name': 'Toplam Enerji',
        'code': 'add_ele',
        'type': int,
        'access': 'ro',
        'max': 50000,
        'min': 0,
        'scale': 3,
        'step': 100,
        'format': lambda x: f'{x/1000:.3f} kWh'
    },
    '18': {
        'id': 18,
        'name': 'Anlık Akım',
        'code': 'cur_current',
        'type': int,
        'access': 'ro',
        'max': 30000,
        'min': 0,
        'unit': 'mA',
        'format': lambda x: f'{x/1000:.2f} A'
    },
    '19': {
        'id': 19,
        'name': 'Anlık Güç',
        'code': 'cur_power',
        'type': int,
        'access': 'ro',
        'max': 80000,
        'min': 0,
        'scale': 1,
        'unit': 'W',
        'format': lambda x: f'{x/10:.1f} W'
    },
    '20': {
        'id': 20,
        'name': 'Anlık Voltaj',
        'code': 'cur_voltage',
        'type': int,
        'access': 'ro',
        'max': 5000,
        'min': 0,
        'scale': 1,
        'unit': 'V',
        'format': lambda x: f'{x/10:.1f} V'
    },
    '21': {
        'id': 21,
        'name': 'Test Sonucu',
        'code': 'test_bit',
        'type': int,
        'access': 'ro',
        'max': 5,
        'min': 0,
        'format': lambda x: f'Test Sonucu: {x}'
    },
    '26': {
        'id': 26,
        'name': 'Hata Durumu',
        'code': 'fault',
        'type': int,
        'access': 'ro',
        'labels': ['Aşırı Akım', 'Aşırı Voltaj', 'Aşırı Güç', 'Düşük Akım', 'Düşük Voltaj', 'Düşük Güç'],
        'format': lambda x: decode_fault(x)
    },
    '38': {
        'id': 38,
        'name': 'Röle Durumu',
        'code': 'relay_status',
        'type': str,
        'access': 'rw',
        'icon': 'icon-zhuangtai',
        'range': ['off', 'on', 'memory'],
        'format': lambda x: {'off': 'Kapalı', 'on': 'Açık', 'memory': 'Hafıza'}.get(x, x)
    },
    '39': {
        'id': 39,
        'name': 'Aşırı Şarj Koruması',
        'code': 'overcharge_switch',
        'type': bool,
        'access': 'rw',
        'format': lambda x: 'Aktif' if x else 'Pasif'
    },
    '40': {
        'id': 40,
        'name': 'LED Gösterge Modu',
        'code': 'light_mode',
        'type': str,
        'access': 'rw',
        'icon': 'tcl_function_light',
        'range': ['relay', 'pos', 'none', 'on'],
        'format': lambda x: {'relay': 'Röle', 'pos': 'Pozisyon', 'none': 'Kapalı', 'on': 'Açık'}.get(x, x)
    },
    '41': {
        'id': 41,
        'name': 'Çocuk Kilidi',
        'code': 'child_lock',
        'type': bool,
        'access': 'rw',
        'icon': 'icon-dp_power2',
        'format': lambda x: 'Kilitli' if x else 'Kilitsiz'
    },
    '42': {
        'id': 42,
        'name': 'Döngü Zamanlayıcı',
        'code': 'cycle_time',
        'type': str,
        'access': 'rw',
        'icon': 'icon-dp_time3',
        'maxlen': 255,
        'format': lambda x: f'Döngü: {x}'
    },
    '43': {
        'id': 43,
        'name': 'Rastgele Zamanlayıcı',
        'code': 'random_time',
        'type': str,
        'access': 'rw',
        'icon': 'icon-dp_time2',
        'maxlen': 255,
        'format': lambda x: f'Rastgele: {x}'
    },
    '44': {
        'id': 44,
        'name': 'Anlık Anahtar',
        'code': 'switch_inching',
        'type': str,
        'access': 'rw',
        'maxlen': 255,
        'format': lambda x: f'Anlık: {x}'
    }
}

def decode_fault(fault_code):
    faults = []
    fault_map = {
        0: "Aşırı Akım",
        1: "Aşırı Voltaj", 
        2: "Aşırı Güç",
        3: "Düşük Akım",
        4: "Düşük Voltaj",
        5: "Düşük Güç"
    }
    
    for bit, fault in fault_map.items():
        if fault_code & (1 << bit):
            faults.append(fault)
    
    return ', '.join(faults) if faults else 'Normal'

def check_device_status(device):
    try:
        status = device.status()
        
        if status and 'dps' in status:
            dps = status['dps']
            print("\n=== Cihaz Durumu ===")
            
            for key, value in dps.items():
                if key in DPS_MAPPING:
                    mapping = DPS_MAPPING[key]
                    try:
                        if isinstance(value, mapping['type']):
                            formatted_value = mapping['format'](value)
                            print(f"{mapping['name']}: {formatted_value}")
                        else:
                            print(f"{mapping['name']}: Tip hatası")
                    except Exception as e:
                        print(f"{mapping['name']}: Formatlama hatası - {str(e)}")
            
            print("\n=== Ham Veri ===")
            print(status)
        else:
            print("Cihaz durumu alınamadı!")
            
    except Exception as e:
        print(f"Durum kontrolünde hata: {e}")
        return None

def connect_device():
    try:
        device = tinytuya.OutletDevice(
            dev_id=DEVICE_ID,
            address=IP_ADDRESS,
            local_key=LOCAL_KEY
        )
        device.set_version(VERSION)
        return device
    except Exception as e:
        print(f"Cihaz bağlantısı hatası: {e}")
        return None

def main():
    device = connect_device()
    if not device:
        print("Program sonlandırılıyor...")
        return
    
    print("Cihaza bağlanıldı...")
    check_device_status(device)

if __name__ == "__main__":
    main()

kodu çalıştırınca aşagıdaki çıktı ile karşılacağız…

Cihaza bağlanıldı...

=== Cihaz Durumu ===
Güç Anahtarı: Açık
Geri Sayım: 0 saniye
Toplam Enerji: 0.100 kWh
Anlık Akım: 1.24 A
Anlık Güç: 279.3 W
Anlık Voltaj: 233.1 V
Test Sonucu: Test Sonucu: 1
Hata Durumu: Normal
Röle Durumu: Hafıza
Aşırı Şarj Koruması: Pasif
LED Gösterge Modu: Röle
Çocuk Kilidi: Kilitsiz
Döngü Zamanlayıcı: Döngü:
Rastgele Zamanlayıcı: Rastgele:
Anlık Anahtar: Anlık:

=== Ham Veri ===
{'dps': {'1': True, '9': 0, '17': 100, '18': 1242, '19': 2793, '20': 2331, '21': 1, '22': 567, '23': 27594, '24': 14940, '25': 2780, '26': 0, '38': 'memory', '39': False, '40': 'relay', '41': False, '42': '', '43': '', '44': ''}}

şimdilik bu kadar…. ikinci bir yazı olursa veriyi loglamayı, analizi ve açıp kapama örneklerini anlatacağım…

Vücut kütle endeksi

kilo almaya başlayınca vücut kütle endeksini ögreniyorsunuz.

vke = kilo / boy^2

şeklinde bir formülü varmış. boy metre cinsinden olmalı.. bunu ögrendiğimize göre oturduğumuz yerden beynimizde ve parmaklarımızda bir miktar kalori yakalım.

bu formül için bir api yapalım… api GET ile yapılan isteğe json dönüşü yapsın. bunu python – flask kullanarak gerçekleştirelim.

from flask import Flask, request, jsonify

app = Flask(__name__)

# Vücut Kitle Endeksi Hesaplama Fonksiyonu
def hesapla_vke(kilo, boy):
    try:
        # Boy metre cinsinden olmalı, örneğin: 1.75 m
        vke = kilo / (boy ** 2)
        return vke
    except ZeroDivisionError:
        return "Boy 0 olamaz!"
    except Exception as e:
        return str(e)

# VKE Kategorisini Belirleyen Fonksiyon
def vke_kategorisi(vke):
    if vke < 18.5:
        return "Zayıf"
    elif 18.5 <= vke < 24.9:
        return "Normal"
    elif 25 <= vke < 29.9:
        return "Fazla Kilolu"
    else:
        return "Obez"

# VKE Hesaplamak
@app.route('/hesapla_vke', methods=['GET'])
def hesapla():
    # URL parametreleri ile kilo ve boy alıyoruz
    kilo = request.args.get('kilo', type=float)
    boy = request.args.get('boy', type=float)

    # Kilo ve boy parametrelerinin kontrolü
    if kilo is None or boy is None:
        return jsonify({"error": "Lütfen 'kilo' ve 'boy' parametrelerini giriniz!"}), 400

    # VKE'yi hesaplayalım
    vke = hesapla_vke(kilo, boy)
    
    if isinstance(vke, str):  # Eğer hata mesajı döndüyse
        return jsonify({"error": vke}), 400
    
    # Kategoriyi belirleyelim
    kategori = vke_kategorisi(vke)

    # Sonucu JSON formatında döndürelim
    return jsonify({
        "kilo": kilo,
        "boy": boy,
        "vke": vke,
        "kategori": kategori
    })


if __name__ == '__main__':
    app.run(debug=True, port=5000)

pythonla metin şeklindeki zaman bilgisini ayrıştırmak

dateparser, datefinder gibi bir modul kullanma imkanınız yoksa metin şeklinde yazılmış bir zaman verisini nasıl işleyebiliriz basit bir örnek yapalım.

3 yıl 4 ay 5 gün 10 dakika şeklinde yazılmış bir zaman verisinin kaç dakika olduğunu hesaplayalım.

öncelikle uygun bir regex oluşturalım. daha optimize şekilde yazılabilir ancak ben aşagıdaki yapıyı kullanacağım.

desenler = {
    'YIL': re.compile(r'(\d+)\s*[Yy][İiIi][Ll]', re.I),
    'AY': re.compile(r'(\d+)\s*[Aa][Yy]', re.I),
    'HAFTA': re.compile(r'(\d+)\s*[Hh][Aa][Ff][Tt][Aa]', re.I),
    'GUN': re.compile(r'(\d+)\s*[Gg][ÜuUu][Nn]', re.I),
    'SAAT': re.compile(r'(\d+)\s*[Ss][Aa][Aa][Tt]', re.I),
    'DAKIKA': re.compile(r'(\d+)\s*[Dd][Aa][Kk][İiIi][Kk][Aa]', re.I),
    'SANIYE': re.compile(r'(\d+)\s*[Ss][Aa][Nn][İiIi][Yy][Ee]', re.I)
}

şimdide dakika dönüşü için gerekli hesaplamayı yapacağız listeyi oluşturalım.

dakika_donusturme = {
    'YIL': 365 * 24 * 60,
    'AY': 30 * 24 * 60,
    'HAFTA': 7 * 24 * 60,
    'GUN': 24 * 60,
    'SAAT': 60,
    'DAKIKA': 1,
    'SANIYE': 1 / 60
}

sırada ise metin bilgisini oluşturacak fonksiyonu yazalım.

def metin_ifadesinden_dakika_hesapla(metin_ifadesi):
    if not isinstance(metin_ifadesi, str)  or metin_ifadesi == "":      
        return None
    
    zaman_birimleri = {}

    for birim, desen in desenler.items():
        eslesme = desen.search(metin_ifadesi)
        zaman_birimleri[birim] = int(eslesme.group(1)) if eslesme else 0

    toplam_dakika = sum(zaman_birimleri[birim] * dakika_donusturme[birim] for birim in zaman_birimleri)

    return int(toplam_dakika)

kodumuzu çalıştırdığımız zaman

"3 yıl 4 ay 5 gün 10 dakika" zaman verisi toplam 1756810 dakikadır

çıktısını elde ederiz.

python’da büyük veri kümelerinde ortalama değer hesaplama

ortalama değer bir veri kümesindeki sayıların toplamının eleman sayısına bölümü olarak hesaplanır.

bunu yapacak bir fonksiyon yazalım.

def ortalama_bul(veri_kumesi):
    toplam = sum(veri_kumesi)
    eleman_sayisi = len(veri_kumesi)
    ortalama = toplam / eleman_sayisi
    return ortalama

bu yöntem düşük boyutlu veri kümeleri ile çalışırken yeterli olacaktır ancak veri kümesi büyüdükçe dahah hızlı bir yöntem gerekecektir. bu durumu yapacağımız örnekle inceleyelim.

numpy ile belirli boyutta bir veri kümeisi oluşturalım. yazdığımız fonkisyon ve alternatif olarak numpy nin mean metodu ile ortalama değeri hesaplamasını yapabilecek bir kod yazalım. hesaplamanın ne kadar sürede yapıldığını öğrenmek adına basit bir time yöntemi eklemeyi unutmayalım.

import numpy as np
import time

# Veri kümesinin ortalamasını bulan fonksiyon
def ortalama_bul(veri_kumesi):
    toplam = sum(veri_kumesi)
    eleman_sayisi = len(veri_kumesi)
    ortalama = toplam / eleman_sayisi
    return ortalama

# veri kümesi oluştur
veri_kumesi = np.random.rand(10000)

# numpy ile ortalama bulma
np_baslangic_zamani = time.time()
np_ortalama = np.mean(veri_kumesi)
np_bitis_zamani = time.time()
print(f"Numpy ile Ortalama hesaplama süresi: {np_bitis_zamani - np_baslangic_zamani} saniye")
print(f"Numpy ile Veri kümesinin ortalaması: {np_ortalama}")


# ortalama_bul fonksiyonunu kullanarak ortalama bulma
fonk_baslangic_zamani = time.time()
fonk_ortalama = ortalama_bul(veri_kumesi)
fonk_bitis_zamani = time.time()
print(f"Fonksiyon Ortalama hesaplama süresi: {fonk_bitis_zamani - fonk_baslangic_zamani} saniye")
print(f"Fonksiyon ile Veri kümesinin ortalaması: {fonk_ortalama}")

yukarıdaki kodda 10.000 adet veri için ortalama hesapları yapılmaktadır. kodu çalıştırdığımda elde ettiğim sonuç aşagıdaki gibidir.

Numpy ile Ortalama hesaplama süresi: 0.0 saniye
Numpy ile Veri kümesinin ortalaması: 0.5017341979294518
Fonksiyon Ortalama hesaplama süresi: 0.0 saniye
Fonksiyon ile Veri kümesinin ortalaması: 0.5017341979294502

veri boytunu katlayarak sonuçları kıyaslayalım. 100.000 değer için.

Numpy ile Ortalama hesaplama süresi: 0.0 saniye
Numpy ile Veri kümesinin ortalaması: 0.5008137222243555
Fonksiyon Ortalama hesaplama süresi: 0.0 saniye
Fonksiyon ile Veri kümesinin ortalaması: 0.5008137222243564

1.000.000 değer için

Numpy ile Ortalama hesaplama süresi: 0.0 saniye
Numpy ile Veri kümesinin ortalaması: 0.5000936635960163
Fonksiyon Ortalama hesaplama süresi: 0.046967267990112305 saniye
Fonksiyon ile Veri kümesinin ortalaması: 0.5000936635960234

hesaplamalarda ufak farklar görülmeye başladı. 10.000.000 için

Numpy ile Ortalama hesaplama süresi: 0.014102935791015625 saniye
Numpy ile Veri kümesinin ortalaması: 0.5002303952512933
Fonksiyon Ortalama hesaplama süresi: 0.5047390460968018 saniye
Fonksiyon ile Veri kümesinin ortalaması: 0.5002303952512889

aradaki fark artıyor. verimizi arttırmaya devam. 100.000.000 için

Numpy ile Ortalama hesaplama süresi: 0.09502911567687988 saniye
Numpy ile Veri kümesinin ortalaması: 0.49998983843975686
Fonksiyon Ortalama hesaplama süresi: 5.2369115352630615 saniye
Fonksiyon ile Veri kümesinin ortalaması: 0.4999898384397282

olarak bir çıktı elde ediyoruz. artık hesaplama süresini hissetmeye başladık. durmak yok veriyi büyütmeye devam

Traceback (most recent call last):
  File "D:\python\ortalama.py", line 13, in <module>
    veri_kumesi = np.random.rand(1000000000)
  File "numpy\\random\\mtrand.pyx", line 1218, in numpy.random.mtrand.RandomState.rand
  File "numpy\\random\\mtrand.pyx", line 436, in numpy.random.mtrand.RandomState.random_sample
  File "_common.pyx", line 307, in numpy.random._common.double_fill
numpy.core._exceptions._ArrayMemoryError: Unable to allocate 7.45 GiB for an array with shape (1000000000,) and data type float64

1 Milyar için hesaplama yapmak istediğimde ise numpy için kırılma noktasına gelmiş olduğumuz görüyoruz. numpy ile devam etmek istiyorsak veri kümesini bölerek işlem yapmalıyız. buna uygun basit bir kod yazalım.

import numpy as np
import time

# Veri kümesinin boyutu ve parça boyutu
veri_boyutu = 1000000000
parca_boyutu = 100000

# Ortalamaları saklamak için bir liste oluştur
ortalama_listesi = []

np_baslangic_zamani = time.time()

# Veri kümesini parçalara böl ve her parçanın ortalamasını hesapla
for _ in range(veri_boyutu // parca_boyutu):
    veri_kumesi = np.random.rand(parca_boyutu)
    ortalama = np.mean(veri_kumesi)
    ortalama_listesi.append(ortalama)

# Tüm parçaların ortalamasını hesapla
genel_ortalama = np.mean(ortalama_listesi)
np_bitis_zamani = time.time()

print(f"Veri kümesinin genel ortalaması: {genel_ortalama}")
print(f"Ortalama hesaplama süresi: {np_bitis_zamani - np_baslangic_zamani} saniye")

bu kod içinde parca_boyutu artııkça toplam hesaplama süresinin uzadığı görülmektedir.

işleri daha karmaşık hale getirmek istemiyorsak dask modulünü kullanmak farklı çözüm olacaktır.

import dask.array as da
import dask
import time

dask_baslangic_zamani = time.time()

# örnek veri kümesi oluştur
veri_kumesi = da.random.random(size=(1000000000,), chunks=1000000)

# Ortalama hesaplama
ortalama = da.mean(veri_kumesi)

# Dask hesaplamasını başlatma
with dask.config.set(scheduler='threads'):
    sonuc = ortalama.compute()

dask_bitis_zamani = time.time()

# Hesaplanan ortalama değeri ekrana yazdırma
print(f"Veri kümesinin ortalaması: {sonuc}")
print(f"Dask ile Ortalama hesaplama süresi: {dask_bitis_zamani - dask_baslangic_zamani} saniye")

dask ile çalışırkenden chunks değeri hesaplama sürenizi eklieyecektir. 1 milyar değer için 100 bin değeri bende en optimal sonucu veriyor.

1 milyar veri için dask ve numpy de en optimal parametreler ile elde edilen sonuçlar aşagıdaki gibi çıkmakta…

dasknumpy
1 milyar veri1 milyar veri
2.631504535675049 saniye5.981382369995117 saniye

buradaki kodlar en optimal kodlar olmayabilir ve daha hızlı yöntemler oluşturulabilir. ancak bu haliyle kişisel bigisayarımda 1 milyar ve üzeri veriler için dask kullanmak çok daha mantıklı geliyor.

hareketli ortalama ve standart sapma ile anomali tespiti örneği

bir zaman serisinde anormal noktaların tespitinde kullanılabilecek yöntemlerden bir tanesi hareketli ortalama ve standart sapma kullanmaktadır. basit bir python uygulaması yapalım…

çıktıdan görüleceği gibi doğruluk oranı tüm uygulamalar için işe yaramayabilir. anomali tespiti giriş seviye uygulamalarda kullanılabilir.

python kodlarını çalıştırılabilir (.exe) dosya yapmak

pythonda çalışmanın dezavantajlarından bir tanesi yazdığınız kodları işletim sisteminde çalıştırabilir dosya haline getirme konusudur. çok fazla tercih etmesemde bazen gerekebiliyor.. bu noktada birden fazla seçenek mevcut ancak genel olarak en popüler olanları kullanmak daha fazla kütüphane v.b. konuda soun yaşamamanızı sağlıyor.

pyinstaller seçeneklerin en popüleri diye biliriz. tabiki ilk önce kurmamız gerekiyor.

pip install pyinstaller

kurulumu tamamladıktan sonra kullanımı oldukça kolay. komut yorumluyacısında ihtiyacımız olan parametreleri girerek exe dosyasını oluşturuyoruz.

pyinstaller --onefile dosyaadi.py

komut tamamlandığından python dosyasının bulunduğu klasör içine dist ve build isimli iki yeni klasör oluştuğunu göreceksiniz. dist klasöründen exe dosyanız build klasöründen ise exe oluşturma sürecinde kullanılan dosyalar yer almaktadır.

yukarıdaki komut yapısını kullandığınızda yazdığınız kod ihtiyaç duyulan tüm sistem dosyalarını tek bir dosya içine dahil etmektedir. bu nedenden dolayı dist klasöründeki exe dosyasına incelediğinizde yazdığımız üç beş satır koda karşı oldukça büyük boyutlu olduğunuz göreceksiniz.

eğer gui şeklinde bir uygulama yaptızsanız programı çalıştırdığınız ilave bir console pencesi açılmaması adına noconsole parametresinin eklenmesi gerekmektedir.

pyinstaller --onefile --noconsole dosyaadi.py

oluşturlan dosyanın iconunu değiştirme gibi bir çok seçenek için https://pyinstaller.org/ adresi incelemenizi öneririm.

pythonda dosya içeriği karşılaştırma

iki text dosya içeriği arasındaki farkları bulmak için temel olarak dosyaları satır satır olarak okuyup satıları karşılaştırmak gerekmektedir. bu işlemi kod olarak basitleştirme adına python kullanabilieceğiniz bir çok kütüphane bulunmaktadır. bunlardan en kullanışlarıdan bir tanesi difflib dir.

aşagıdaki örnekte importlardan sonra dosyaların içeriğindeki satırları bir diziye atadıktan sonra difflib de dizi girişlerini ve istediğimiz çıktıyı tanımlarıyoruz..

import difflib
from pathlib import Path

first_file_lines = Path('fileA.txt').read_text().splitlines()
second_file_lines = Path('fileB.txt').read_text().splitlines()

html_out = difflib.HtmlDiff().make_file(first_file_lines, second_file_lines)
Path('diff_output.html').write_text(html_out)
fileA.txtfileB.txt
first_file_lines = Path(‘fileA.txt’)
second_file_lines = Path(‘fileB.txt’)
first_file_lines = Path(‘fileA.txt’)
second_file_lines = Path(‘file2.txt’).read_text()

diff_output.html aşagıdaki şekilde görülecektir.

python örnekleri : hafıza kullanım bilgileri

Python’da kullanılabilir hafıza bilgisini öğrenmek için psutil adlı bir modül kullanabilirsiniz. Bu modül, sistem hafıza bilgisi gibi çeşitli sistem verilerine erişmenize izin verir. Örnek olarak, aşağıdaki kod parçacığı hafıza kullanım bilgisini gösterir:

import psutil

memory = psutil.virtual_memory()

print(f"Hafıza kullanım oranı: {memory.percent}%")

print(f"Kullanılabilir hafıza: {memory.available // (1024 ** 2)} MB")

Bu kod, hafıza kullanım oranını yüzdesini ve kullanabilir hafızayı MB cinsinden ekrana yazdıracaktır. psutil modülünü kullanmadan önce sisteminize yüklemeniz gerekebilir. Bunun için aşağıdaki komutu kullanabilirsiniz:

pip install psutil

python örnekleri : cpu sayısı

Python’da bir sistemdeki CPU sayısını öğrenmek için multiprocessing modülünü kullanabilirsiniz. Örnek kod aşağıdaki gibidir:

import multiprocessing

# Sistemdeki CPU sayısını alın
cpu_count = multiprocessing.cpu_count()

print(f"CPU sayısı: {cpu_count}")

Back To Top