SOCKET programlamada fonksiyon içindeki DEĞİŞKENİ BAŞKA BİR FONKSİYONDA TANIMLAMA !

global alanda none olarak belirtiğim için 2 .fonksiyonun içinde değerini none olarak alıyor bu hatayı veriyor;
“”"
AttributeError: ‘NoneType’ object has no attribute ‘send’
“”"
yani yapmam gereken değişkeni birinci fonksiyonun içinde globalleştirmek

Zaten size f_ara() fonksiyonunun içine client değişkenini aktaracaksınız diye belirtmiştim.

atadımda diğer fonksiyonun içinde aynı değişkeni bahsettiğimde globalı baz alıyor yani none

Son kodlarınızı kod görünümünde paylaşır mısınız? Bir de sınıfları kullansanız bu gibi sorunlarla karşılaşmazsınız diye düşünüyorum.

İsmail Bey’in dediği gibi kodlarınızı burada kod görünümüne alarak paylaşabilir misiniz?

Normalde global alanda bir client değişkeni tanımlayıp, f_ara() fonksiyonunun içinde bu global değişkeni değiştirirseniz, başka bir fonksiyonun içinde kullandığınız client’in değeri değiştirilen değer olur. Bu uygulayabileceğiniz yöntemlerden biridir yeter ki global alandaki client değişkenini değiştirdiğiniz fonksiyonu, client ile işlem yapacağınız diğer fonksiyonlardan önce çalıştırın ki client’in değeri değişsin.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket

client = None


def socket_olustur():
    global client
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = "localhost"
    port = 1236
    s.bind((host, port))
    s.listen(1)
    client, address = s.accept()


def gonder():
    client.send("merhaba".encode("utf-8"))


# Önce socket_olustur() fonksiyonunu çağırmalısınız ki
# client değişkeninin değeri değişsin. Ki zaten socket işlemleri
# yapabilmek için de önce bu fonksiyonu çağırmalısınız.
socket_olustur()
# Sonra clientin yaptığı işle ilgili başka bir fonksiyonu
# kullanabilirsiniz.
gonder()

Diğer bir yöntem ise İsmail Bey’in de dediği gibi sınıfları kullanmanızdır.

Üçüncü bir yöntem daha var, o da şu: global alanda boş bir liste tanımlayın. client, adres = listener.accept()'i yazdığınız satırdan sonra bu tanımladığınız listeye client’i ekleyin. Başka bir fonksiyonda client’e ihtiyacınız olduğunda bu listenin elemanını kullanabilirsiniz.

Bu yolu ben anlayamadım. Biraz daha açar mısınız? global yolundan bir farkı var mı bu yolun?

Tamam, örnek üzerinden göstermeye çalışayım.

Bir önceki mesajımdaki örnekte global alandaki client değişkenini fonksiyonun içine çekmiştik, bu sefer de aşağıdaki yolu izliyoruz:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket


clients = []


def socket_olustur():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = "localhost"
    port = 1236
    s.bind((host, port))
    s.listen(1)
    client, address = s.accept()
    clients.append(client)


def gonder():
    clients[0].send("merhaba".encode("utf-8"))


socket_olustur()
gonder()

Not: Bu bahsettiklerim, sadece arkadaşın takıldığı yerle alakalı bir çözüm üretir. Normalde düzgün bir haberleşmeyle alakalı bir program oluşturabilmek için programa daha çok eklemeler, düzenlemeler yapmak lazım.

Burada neden clientsglobal olarak tanımlamadık, listelerde bir istisna mı var?

Fonksiyonun içinde listenin append metodunu çağırarak, listeye eleman ekledik. Ama mesela liste kullandığımız yerde demet tipinde bir veri kullanamazdık. Yani şöyle anlatmaya çalışayım:

demet = tuple()


def f():
    demet += "hello",
    print(demet[0])


f()
# Bu işlemi gerçekleştiremeyiz.

Yukarıda yapmak istediğimiz işlemi şu şekilde yazmamız gerekiyor:

demet = tuple()

def f():
    global demet
    demet += "hello",
    print(demet[0])

f()

Aynı durum str(), int() gibi immutable veri tipleri için de geçerli. Çünkü bunların doğrudan veriye eleman ekleme yöntemleri yok. Mesela bir stringe veya demete eleman eklerken += ifadesini kullanıyoruz. Aynı durum sayıyı değiştirirken de geçerli.

Ama list(), dict(), set() gibi mutable veri tiplerinin kendilerine ait birer eleman ekleme yöntemleri var. Ve bu yöntemler bir fonksiyonun içinde kullanılabilir.

Bu arada, eğer bu immutable veri tiplerine ait yöntemlerin fonksiyon içerisinde kullanılması söz konusuysa, bunun için değişkenin başına global yazarak fonksiyonun içine aktarılması gerekmiyor.

Örneğin:

demet = tuple(["hello", "world"])


def f():
    for i in demet:
        print(demet.index(i))


f()

Başka bir örnek:

string = "hello"


def f():
    for i in string:
        print(i)

f()
1 Beğeni

ben tkinter ile mesaj göndermeye çalışyorum ama dediğim hatayı alıyorum. Kodaların tamamı böyle ;


Dediğiniz gibi global yaptığımdada aynı hatayı aldım.

Kodları buraya ekran görüntüsü olarak değil de kod görünümünde aktarabilir misiniz? Bir de global değişkeni nasıl kullandınız onu da yine kod görünümü içinde paylaşabilir misiniz?

[code]
Kodların tamamının bu aralığa yazılması lazım.
[/code]

global client şeklinde yazdığım kodlar böyle ;


import tkinter as m_tk
import socket as m_soc

fr_form = m_tk.Tk()

client = None

def f_ara():
    listener = m_soc.socket(m_soc.AF_INET, m_soc.SOCK_STREAM)

    host = "localhost"
    port = 8

    listener.bind((host, port))
    listener.listen(1)
    client, adres = listener.accept()
    print(adres)

def f_gonder():
    mesaj = e_mesaj.get()
    client.send(mesaj.encode("ascii"))
    l_label["text"] = "GÖNDERİLDİ"
    #l_label["text"] = client.recv(1024).decode("ascii")

def f_kapat():
    client.close()

e_mesaj = m_tk.Entry(fr_form)
e_mesaj.pack()

l_label = m_tk.Label(fr_form, text = "listener")
l_label.pack()

b_baslat = m_tk.Button(fr_form, text = "BAŞLAT", command = f_ara)
b_baslat.pack()

b_gonder = m_tk.Button(fr_form, text = "GÖNDER", command = f_gonder)
b_gonder.pack()

b_kapat = m_tk.Button(fr_form, text = "KAPAT", command = f_kapat)
b_kapat.pack()

fr_form.mainloop()

aldığım hata da ;
AttributeError: ‘NoneType’ object has no attribute ‘send’
böyle.

İyi ama bu kodlarda f_ara() fonksiyonun içinde global client yok ki. Size daha önceki mesajlarımdan birinde demiştim ki, global client’i f_ara fonksiyonunun içine aktarın, tıpkı aşağıdaki gibi:

def f_ara():
    global client
    listener = m_soc.socket(m_soc.AF_INET, m_soc.SOCK_STREAM)

    host = "localhost"
    port = 8

    listener.bind((host, port))
    listener.listen(1)
    client, adres = listener.accept()
    print(adres)

ama sizin paylaştığınız kodlarda bu yapılmamış.

1 Beğeni

aynn öyle bunu farketmemişim :smiley: yardımcı olan herkese teşekkür ederim.

sınıfları kullanarak nasıl yapabilirdim onuda gösterirmisiniz?

Aslında sınıflarla yapılmış socket uygulamalarına dair yeterince örnek Python Socket Ve Threading Kaynak Bilen Var mı? başlığında ve Socket Modülüyle Yapılmış Chat Uygulaması Örnekleri başlığında mevcut. Oradaki çalışmaları inceleyebilirsiniz. İlk linkteki çalışmalar aşama aşama gelişmiş bir iki programın gelişim süreçlerini daha çok konu ediniyor. İkinci linkteki çalışmalar ise sonuçlanmış çalışmaları paylaştığım bir konu oldu.

baktım da class(sınıf) ile tanımlanmış örnek göremedim çok kod olduğundan da olabilir zahmet olmazsa sadece bir örnek paylaşsanız global yerine nasıl yapılır anlamam için maksad kafam karışmasın verdiğim fonksiyonu kullanarakta yapsanız olur

Yazdığınız kodlar şu şekilde sınıfa dönüştürülebilir. Bu arada bu tip uygulamalarda threading’i kullanmanızı öneririm.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import threading
import tkinter as m_tk
import socket as m_soc

fr_form = m_tk.Tk()


class Server(m_soc.socket):
    clients = []

    def __init__(self):
        m_soc.socket.__init__(self, m_soc.AF_INET, m_soc.SOCK_STREAM)
        host = "localhost"
        port = 1234
        self.bind((host, port))
        self.listen(1)

    def kabul_et(self):

        def f():
            client, adres = self.accept()
            self.clients.append(client)

        t = threading.Thread(target=f)
        t.start()

    def mesaj_gonder(self):

        def f():
            mesaj = e_mesaj.get()
            self.clients[0].send(mesaj.encode("ascii"))
            l_label["text"] = "GÖNDERİLDİ"

        t = threading.Thread(target=f)
        t.start()

    def kapat(self):
        self.clients[0].close()


server = Server()

e_mesaj = m_tk.Entry(fr_form)
e_mesaj.pack()

l_label = m_tk.Label(fr_form, text = "listener")
l_label.pack()

b_baslat = m_tk.Button(fr_form, text = "BAŞLAT", command=server.kabul_et)
b_baslat.pack()

b_gonder = m_tk.Button(fr_form, text = "GÖNDER", command=server.mesaj_gonder)
b_gonder.pack()

b_kapat = m_tk.Button(fr_form, text = "KAPAT", command=server.kapat)
b_kapat.pack()

fr_form.mainloop()

Yalnız bu uygulama baya eksik bir uygulama. Lütfen okumanızı önerdiğim başlıkların mesajlarını bir okuyun. İnanıyorum ki ciddi bir şekilde okursanız, size faydası olacaktır.

1 Beğeni

@dildeolupbiten, Allah razı olsun. global konusunu şimdiye kadar tam olarak anlayamamıştım. Anladığım kadarıyla global'in amacı global alandaki değişkenlerin istemsiz şekilde değiştirilmesini engellemek. global değişken_adı yazarak aslında “Ben bu değişkeni burada bilerek değiştiriyorum, herhangi bir sorun yok.” demek istiyoruz. Mutable tipler ve yöntem çağrımları değişkenin değerini değiştirmediği için bunlarda böyle bir ifade kullanmak gerekmiyor.

Aynen öyle. Python’ın böyle durumlarda verdiği hata UnboundLocalError: local variable 'değişken_adı' referenced before assignment hatasıdır. Lokal değişkeni atamadan referans göstermeye çalışıyorsun demek istiyor.

Bu arada bir şeyi hatalı belirtmişim onu da düzeltmek istiyorum. Yukarıda bahsettiğim hata list() kullanıldığında da geçerli oluyor:

liste = list()


def f():
    liste += "hello",
    print(liste[0])


f()

Bu işlemi yapabilmek için de global liste’yi fonksiyonun içine eklemek gerekiyor.

liste = list()


def f():
    global liste
    liste += "hello",
    print(liste[0])


f()

Ama listeye genellikle eleman eklerken += kullanmak yerine onun append() metodunu çağırdığımız için global’i kullanmak gerekmiyor. Yani veri tiplerinin yöntemlerini kullanırken global kullanmamız gerekmiyor.

Gözlemlediğim kadarıyla global yukarıda bahsettiğim durumlarda, bir de değeri (yukarıdaki örneklerden birinde olduğu gibi) None olan bir değişkenin değeri bir fonksiyonun içinde değiştirilmek istendiğinde kullanılıyor.

1 Beğeni