jak zwrócić na serwer informację z trwającego wątku?

jak zwrócić na serwer informację z trwającego wątku?
RN
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:5
0

Witam,
Nie ukrywam że niewiele wiem o pythonie, a moim celem nie jest poznanie go dokładnie, tylko możliwie szybkie rozwiązanie problemu, dlatego zwracam się z prośbą o pomoc do bardziej doświadczonych (wszystko co do tej pory znalazłem w sieci rozwiązuje inne przypadki, a w moim się niestety nie sprawdza...).
W skrócie:
Mam serwer obsługujący grę w sieci lokalnej (czy jakiejkolwiek, to akurat nieistotne, komunikacja przeglądarka-serwer działa jak trzeba) - gra wymaga dwóch osób do każdej rozgrywki, gdy znajdzie się dwóch graczy tworzy im 'ich' grę - która jest obsługiwana przez oddzielny wątek (warunek konieczny).
Serwer otrzymuje zapytania z frontu i obsługuje je wywołując odpowiednie funkcje na wątku z konkretną grą.
Plik pythona z grą 'nasłuchuje' na wywołanie funkcji, wykonuje je i powinien zwrócić odpowiedź, ale tego nie robi i tego właśnie dotyczy moje pytanie:

Jak przesłać informację zwrotną z trwającego wątku (gra ciągle się toczy, więc nie kończymy wątku), na serwer (który będzie mógł zrobić z tym co trzeba, wysłać na front itp)?

W uogólnieniu tak wygląda plik z grą (czyli wątkiem):
'''
import queue
import threading

class Game(threading.Thread):
def init(...)
...

def onThread(self, function, *args, **kwargs):
	self.q.put((function, args, kwargs))

def run(self):
	while True:
		try:
			function, args, kwargs = self.q.get(timeout=self.timeout)
			function(*args, **kwargs)
		except queue.Empty:
			self.idle()

def idle(self):
	# put the code you would have put in the `run` loop here 
	pass

def do_sth(self,arg)
	...

...
'''
Z góry dzięki za pomoc.

edytowany 1x, ostatnio: RudeNoob
enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:dzień
  • Postów:1027
0

W jaki sposób komunikujesz się z klientem?

RN
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:5
0
enedil napisał(a):

W jaki sposób komunikujesz się z klientem?

Flaskiem, ale to działa dobrze. Tak samo dobrze działa wywoływanie funkcji z serwera na konkretnym wątku z grą, przekazywanie argumentów. Nie działa tylko 'zwrotka' z gry (wątku) na serwer.

enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:dzień
  • Postów:1027
0

Nie działa, bo protokół HTTP (czy HTTPS) jest bezstanowy (czyli nie możesz zwrócić częściowego wyniku). Właśnie przez te problemy istnieją takie rozwiązania jak WebSockets (polecam poszukać i poczytać).

RN
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:5
0

Może coś źle wytłumaczyłem, ale u mnie gra (wątek) to tylko obsługa tego co się dzieje u klienta, a nie sam klient. Działa dobrze, chcesz to sprawdź (rozgrzebane i nie dokończone ze względu na problem z 1 posta, ale to co działa to działa): https://github.com/gincio/rochambeau

enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:dzień
  • Postów:1027
1

W Pythonie domyślne argumenty są ewaluowane w momencie deklaracji funkcji:
https://stackoverflow.com/questions/1651154/why-are-default-arguments-evaluated-at-definition-time-in-python

Z tego powodu, ten konstruktor jest błędny:

Kopiuj
	def __init__(self, q = queue.Queue(), loop_time = 1.0/60, done = None): 

Kolejka tak stworzona będzie dokładnie raz (niezależnie od liczby obiektów typu Game), i wszystkie te obiekty będą z tej samej korzystać.
Nie wiem czy ten problem wynika z tego, ale być może masz teraz taką sytuację, że wątek nigdy się nie kończy, bo inne wątki piszą do tej kolejki, a Ty ciągle coś z niej wyciągasz.

Możliwe rozwiązanie: zamiast q = queue.Queue() zrób q=None (btw. brak spacji w domyślnych argumentach jest zalecany), a potem zrób typowe if not q: q = queue.Queue().

RN
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:5
0

Okej, poprawię, dzięki - faktycznie nie testowałem tego jeszcze na x wątkach, póki co staram się zrobić np drugą taką kolejkę, która będzie przechowywać wartości wynikowe funkcji zawartych w Game i będzie się ją dało odczytać z Serwera, tylko nie wiem jak to napisać, o ile to możliwe.

enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:dzień
  • Postów:1027
0

Nie wiem, czy dobrze rozumiem co chcesz osiągnąć, ale wydaje mi się, że mógłbyś stworzyć kolejkę w serwerze i przesłać ją do konstruktora gry. Będziesz móc do niej pisać i czytać w serwerze. Trzymaj takie kolejki gdzieś obok miejsca gdzie są trzymane same wątki.

RN
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:5
0

Potrzebuję czegoś (kolejki?) czym mogę sobie przekazywać dane z serwera do konkretnych wątków z grami i z powrotem. Teraz (tak jak jest na gicie) mogę wysyłać z serwera do wątku gry argumenty funkcji razem z ich wywołaniem, funkcja się wykonuje i nie mam jak odczytać jej wyniku. Kiedy zapisywałem wynik do kolejki, na serwerze ta kolejka wciąż była pusta...

edytowany 3x, ostatnio: RudeNoob
enedil
Ale zawsze tworzysz nowy wątek z nową kolejką, a kluczem jest, abyś miał kolejkę nad którą czuwa serwer, a do której też może pisać wątek z grą.
RN
dokładnie, tylko jak to napisać (zaimplementować)? Próbowałem rozwiązań które wydawały mi się logiczne (moim 'naturalnym' językiem jest C#), ale albo nie działały, albo były traktowane jako błąd składniowy...
enedil
słownik_kolejek[id] = queue.Queue() słownik_gier[id] = Game(q = słownik_kolejek[id])
RN
tak już próbowałem - kolejka powstaje, przesyłam ją do wątku, tam dodaję do niej wynik wywołanej funkcji, próbuję odczytać na serwerze, a serwer mówi że kolejka jest pusta. stąd mój wniosek że brakuje mi jakiejś metody która tą kolejkę będzie synchronizować/przesyłać w drugą stronę... chyba że zwyczajnie mylę się z składni... uaktualnię gita, będzie widać.
enedil
Ja dostaję taki błąd: AttributeError: 'Queue' object has no attribute 'insert' (istotnie, istnieje put).
RN
mi nie wyrzucał tego, ale zorientowałem się już i poprawiłem, wciąż zwraca mi informację że kolejka jest pusta :/
enedil
Hmm, nie wiem o co może chodzić, przepraszam. Od siebie mogę tylko dodać, że powinienieś się zastanowić, gdzie (w kodzie) oczekujesz, że coś się wrzuci, i sprawdzić czy to się tam dzieje, jeśli nie, cofnąć się trochę itd.
RN
Okej, dzięki za pomoc. Logikę programu ogarniam(chociaż też pewnie mogłaby być lepsza), tyle tylko że tracę godziny na szukaniu błędu/rozwiązania w języku którego właściwie nie znam, dlatego właśnie szukam pomocy na forum... może ktoś jeszcze się znajdzie z jakimś pomysłem, zawsze to 'świeże spojrzenie'.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)