ऐसा इसलिए है क्योंकि विवाद क्लाइंट मॉड्यूल को हर मिनट या तो एक बार नियंत्रण की आवश्यकता होती है।
इसका मतलब है कि कोई भी फ़ंक्शन जो किसी निश्चित समय से अधिक नियंत्रण के लिए नियंत्रण करता है, विवाद के क्लाइंट को अमान्य स्थिति में प्रवेश करने का कारण बनता है (जो क्लाइंट के अगले विधि कॉल पर शायद कुछ बिंदु बाद अपवाद के रूप में प्रकट होगा)।
यह सुनिश्चित करने के लिए कि विवाद मॉड्यूल क्लाइंट डिस्कॉर्ड सर्वर को पिंग कर सकता है, आपको एक वास्तविक बहु-थ्रेडिंग समाधान का उपयोग करना चाहिए।
एक समाधान सभी भारी प्रसंस्करण को एक अलग प्रक्रिया पर ऑफ़लोड करना है (एक अलग थ्रेड नहीं करेगा, क्योंकि पाइथन के पास वैश्विक दुभाषिया ताला है) और डिस्कर्ड बॉट का उपयोग पतली परत के रूप में करें जिसका जिम्मेदारी कार्य कतारों को पॉप्युलेट करना है।
संबंधित पढ़ने: https://discordpy.readthedocs.io/en/latest/faq.html#what-does-blocking-mean
उदाहरण समाधान ... इस समस्या के दायरे से बाहर तरीका है, लेकिन मैं पहले से ही कोड ज्यादातर लिखा था।
इस कलह श्रोता है: यदि मैं अधिक समय था, मैं एक छोटी समाधान :)
2 भागों, कलह संपर्क और संसाधन सर्वर लिखेंगे।
import discord
import re
import asyncio
import traceback
import websockets
import json
# Call a function on other server
async def call(methodName, *args, **kwargs):
async with websockets.connect('ws://localhost:9001/meow') as websocket:
payload = json.dumps({"method":methodName, "args":args, "kwargs": kwargs})
await websocket.send(payload)
#...
resp = await websocket.recv()
#...
return resp
client = discord.Client()
tok = open("token.dat").read()
@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
@client.event
async def on_error(event, *args, **kwargs):
print("Error?")
@client.event
async def on_message(message):
try:
if message.author.id == client.user.id:
return
m = re.match("(\w+) for (\d+).*?", message.content)
if m:
g = m.groups(1)
methodName = g[0]
someNumber = int(g[1])
response = await call(methodName, someNumber)
if response:
await client.send_message(message.channel, response[0:2000])
except Exception as e:
print (e)
print (traceback.format_exc())
client.run(tok)
भारी अनुरोधों को संसाधित करने के लिए यह कार्यकर्ता सर्वर है। आप इस हिस्से सिंक या async बना सकते हैं।
मैं कुछ जादू एक WebSocket कहा जाता है एक और एक करने के लिए से एक अजगर की प्रक्रिया से डेटा भेजने के लिए उपयोग करने के लिए चुना है। लेकिन अगर आप कुछ भी आप चाहते हैं का उपयोग कर सकते हैं। आप एक निर्देशिका में एक स्क्रिप्ट लिखने फ़ाइलें बना सकते हैं, और अन्य स्क्रिप्ट फ़ाइलें बाहर पढ़ सकता है और प्रक्रिया उन्हें, उदाहरण के लिए।
import tornado
import tornado.websocket
import tornado.httpserver
import json
import asyncio
import inspect
import time
class Handler:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def consume(self, text):
return "You said {0} and I say hiya".format(text)
async def sweeps(self, len):
await asyncio.sleep(len)
return "Slept for {0} seconds asynchronously!".format(len)
def sleeps(self, len):
time.sleep(len)
return "Slept for {0} seconds synchronously!".format(len)
class MyService(Handler, tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def stop(self):
Handler.server.stop()
def open(self):
print("WebSocket opened")
def on_message(self, message):
print (message)
j = json.loads(message)
methodName = j["method"]
args = j.get("args",())
method = getattr(self, methodName)
if inspect.iscoroutinefunction(method):
loop = asyncio.get_event_loop()
task = loop.create_task(method(*args))
task.add_done_callback(lambda res: self.write_message(res.result()))
future = asyncio.ensure_future(task)
elif method:
resp = method(*args)
self.write_message(resp)
def on_close(self):
print("WebSocket closed")
application = tornado.web.Application([
(r'/meow', MyService),
])
if __name__ == "__main__":
from tornado.platform.asyncio import AsyncIOMainLoop
AsyncIOMainLoop().install()
http_server = tornado.httpserver.HTTPServer(application)
Handler.server = http_server
http_server.listen(9001)
asyncio.get_event_loop().run_forever()
अब, अगर आप अलग अजगर स्क्रिप्ट में दोनों प्रक्रियाओं को चलाने के लिए, और अपने बॉट "100 के लिए नींद" बताओ, यह 100 सेकंड के लिए खुशी से सो जाएगा! एक अस्थायी काम कतार के रूप में asyncio सामान काम करता है, और आप ठीक ढंग से उन्हें अलग अजगर स्क्रिप्ट के रूप में चलाकर बैकेंड संसाधन से श्रोता अलग कर सकते हैं।
अब, कोई फर्क नहीं पड़ता कि आपके सर्वर 'सर्वर' भाग में कितने समय तक चलते हैं, क्लाइंट भाग को कभी भी डिस्कॉर्ड सर्वर को पिंग करने से रोका नहीं जाएगा।
छवि अपलोड करने में विफल रही, लेकिन ... वैसे भी, यह बॉट को सोने और जवाब देने के बारे में बताने के लिए है ... ध्यान दें कि नींद तुल्यकालिक है। http://i.imgur.com/N4ZPPbB.png
विवाद के कार्यकलापों में इस अंतर्दृष्टि के लिए धन्यवाद। दुर्भाग्य से मैं थ्रेडेड और एसिंक्रोनस प्रोग्रामिंग में एक विशेषज्ञ नहीं हूं। क्या आप थोड़ा और समझा सकते हैं कि यह "पतली परत" क्या है और इसे कैसे कार्यान्वित किया जाए? – shrx
कई तरीके हैं, और यह चर्चा इस प्रश्न आईएमओ के दायरे से बाहर है। मैं अपने व्यक्तिगत कोड पर एक ब्राउज़ लेगा (यह काफी बुरा है ... क्योंकि मैंने ओटी लिखा था) और देखें कि क्या मैं आपके लिए कुछ स्निपेट और विचार निकाल सकता हूं :) – JamEnergy
उदाहरण के साथ पूरी तरह से स्पष्टीकरण के लिए धन्यवाद। – shrx