PyQt, Telethon. How to send a message on button click? - pyqt

I am a beginner programmer. It is necessary to send a message to telegram by pressing a button. I use Telethon and PyQt libraries. This code fails with the following error:
sys:1: RuntimeWarning: coroutine 'SendMessage.run' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Process finished with exit code -1073740791 (0xC0000409).
from PyQt6.QtWidgets import *
from telethon import *
from PyQt6.QtCore import QThread
api_id = 'api_id'
api_hash = 'api_hash'
client = TelegramClient('anon', api_id, api_hash, proxy=("http", '192...', 8...))
class SendMassage(QThread):
def __init__(self, mainwindow, parent = None):
super().__init__()
self.mainwindow = mainwindow
async def run(self):
client.start()
await client.send_message('me', 'hello')
client.disconnect()
class SendMessageTest(QDialog):
def __init__(self, parent=None):
super().__init__()
self.PushButton = QPushButton("Send")
self.setGeometry(300,300,300,150)
vbox = QVBoxLayout()
vbox.addWidget(self.PushButton)
self.setLayout(vbox)
self.PushButton.clicked.connect(self.launch_send)
self.sendMessage_instance = SendMessage(mainwindow=self)
def launch_send(self):
self.sendMessage_instance.start()
import sys
app = QApplication(sys.argv)
main = SendMessageTest()
main.show()
sys.exit(app.exec())
Help, please, deal with this problem.

Related

How do I call an async function in a new process using multiprocessing? [duplicate]

This question already has answers here:
FastAPI runs api-calls in serial instead of parallel fashion
(2 answers)
Closed 11 months ago.
I created a server that wait for webhook signal, and when there is signal, it will create a new process to run the loop() function, and when running the loop() function, I want it to call the function printmessage() asynchronously, so it will run the next line in the loop function without waiting the printmessage() function finish processing, but I got the following errors, how I resolve it?
#main.py
import time
from fastapi import Request, FastAPI
import multiprocessing as mp
import uvicorn
import asyncio
async def printmessage(fruit):
print(fruit)
time.sleep(5)
async def loop(fruit):
while True:
task = asyncio.create_task(printmessage(fruit))
time.sleep(1)
fruit="apple"
if __name__ == '__main__':
print("PROGRAM LAUNCH...")
print("WEBHOOK RECEIVE READY...")
app = FastAPI()
#app.post("/webhook")
async def webhook(request : Request):
print("WEBHOOK RECEIVED")
p = mp.Process(target=loop,args=[fruit])
p.start()
print('done')
return 'WEBHOOK RECEIVED'
The intended output should be printing apple every 1 second.
ERRORS:
RuntimeWarning: coroutine 'loop' was never awaited
self._target(*self._args, **self._kwargs)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
I tried the following way to avoid the errors but there is no output at all:
#main.py
import time
from fastapi import Request, FastAPI
import multiprocessing as mp
import uvicorn
import asyncio
async def printmessage(fruit):
print(fruit)
time.sleep(5)
async def loop(fruit):
while True:
task = asyncio.create_task(printmessage(fruit))
time.sleep(1)
def preloop(fruit):
asyncio.run(loop(fruit))
fruit="apple"
if __name__ == '__main__':
print("PROGRAM LAUNCH...")
print("WEBHOOK RECEIVE READY...")
app = FastAPI()
#app.post("/webhook")
async def webhook(request : Request):
print("WEBHOOK RECEIVED")
p = mp.Process(target=preloop,args=[fruit])
p.start()
print('done')
return 'WEBHOOK RECEIVED'
Here is how you can call an async function in a new process using multiprocessing.
In this code, each request to /webhook creates a new process, which prints apple every 5 seconds.
from __future__ import annotations
import asyncio
from multiprocessing import Process
from fastapi import FastAPI
app = FastAPI()
process_pool: list[Process] = []
async def print_message(fruit):
print(fruit)
async def loop(fruit):
while True:
await print_message(fruit)
await asyncio.sleep(5)
def run_loop(fruit):
asyncio.run(loop(fruit))
#app.get("/webhook")
async def webhook():
print("WEBHOOK RECEIVED")
fruit = "apple"
process = Process(target=run_loop, args=(fruit,))
process_pool.append(process)
process.start()
print('done')
return 'WEBHOOK RECEIVED'
#app.on_event("shutdown")
async def shutdown_event():
for process in process_pool:
process.kill()
for process in process_pool:
while process.is_alive():
continue
process.close()
if __name__ == '__main__':
print("PROGRAM LAUNCH...")
print("WEBHOOK RECEIVE READY...")

GET request by QWebEngineHttpRequest (PyQt5)

I want to send a http GET request using QWebEngineHttpRequest.
I know it is possible, as I found this question with a POST request using it.
So, I've ended up with some code but it doesn't work. Let's say I want to make a get request to facebook webpage and print the answer, which should be the HTML content of the page.
import sys
from PyQt5 import *
def handle_response():
print(bytes(replyObject.readAll()).decode("utf-8"))
if __name__ == "__main__":
def app():
app = QApplication(sys.argv)
req = QtWebEngineCore.QWebEngineHttpRequest(QUrl("https://stackoverflow.com/questions/51686198/",
method=QWebEngineHttpRequest.Get)
req.setHeader(QByteArray(b'Content-Type'),QByteArray(b'application/json'))
web = QWebEngineView()
web.loadFinished.connect(on_load_finished) # will be error
sys.exit(app.exec_())
Ok, I found how to make this:
import sys
from PyQt5.QtCore import QByteArray, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineCore import QWebEngineHttpRequest
from PyQt5.QtWebEngineWidgets import QWebEnginePage
class Render(QWebEnginePage):
def __init__(self, url):
app = QApplication(sys.argv)
QWebEnginePage.__init__(self)
self.loadFinished.connect(self._loadFinished)
self._html = ""
username = "username"
password = "password"
base64string = QByteArray(("%s:%s" % (username, password)).encode()).toBase64()
request = QWebEngineHttpRequest(QUrl.fromUserInput(url))
equest.setHeader(b"Authorization", b"Basic: %s" % (base64string,))
self.load(request)
app.exec_()
#property
def html(self):
return self._html
def _loadFinished(self):
self.toHtml(self.handle_to_html)
def handle_to_html(self, html):
self._html = html
QApplication.quit()
def main():
url = "http://www.google.com"
r = Render(url)
print(r.html)
if __name__ == "__main__":
main()
Thanks to link

How make discord.ext.tasks send in channel by id every x minutes in cogs

i tried
# -*- coding: utf-8 -*-
from discord.ext import commands
import discord
import random
import asyncio,json
from discord.ext.commands import clean_content
from datetime import datetime
import aiohttp
from discord.ext import tasks
class Test(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.test1.start()
#tasks.loop(minutes=1.0)
async def test1(self):
channel=bot.get_channel(927612404056092702)
channel.send(mensagem)
def setup(bot):
bot.add_cog(Test(bot))
using
channel=self.bot.get_channel(927612404056092702)
return AttributeError: 'NoneType' object has no attribute 'send'
and using
channel=bot.get_channel(927612404056092702)
return NameError: name 'bot' is not defined
bot.get_channel method retrives channel from cache. You can properly do it only after on_ready event:
class Test(commands.Cog):
def __init__(self, bot):
self.bot = bot
#tasks.loop(minutes=1.0)
async def test1(self):
channel=bot.get_channel(927612404056092702)
channel.send(mensagem)
#commands.Cog.listener()
async def on_ready(self):
if not self.test1.is_running():
self.test1.start()
def setup(bot):
bot.add_cog(Test(bot))

Tornado asynchronous coroutine

Longtime didn't use tornado. I would like to have a websocket which get's updates from a serial device of a host where tornado runs. So I tried multiprocessing with tornado but the process has no access to the tornado websocket. I tried to incorporate it as coroutine but that seems to not not spawn.
class WebApplication(tornado.web.Application):
def __init__(self):
handlers = [
(r'/', IndexPageHandler),
(r"/config", ConfigHandler),
(r"/shutdown", ShutdownHandler),
(r'/websocket', WebSocketHandler),
(r'/(.*)', tornado.web.StaticFileHandler, {'path': resourcesWeb})
]
settings = {
'debug': debug,
'static_path': resourcesWeb,
'template_path': 'templates'
}
tornado.web.Application.__init__(self, handlers, **settings)
#gen.coroutine
def serial_reader(self):
log('serial_reader: start')
done = False
while not done:
sh.read()
serial_data_from = str(sh.data)
if len(serial_data_from) > 0:
if debug:
log('serial read:' + serial_data_from)
yield [con.write_message(serial_data_from) for con in WebSocketHandler.connections]
yield gen.sleep(0.3)
log('serial_reader: exit')
Python 3.8.5, Tornad 6.1
how would I properly and constantly update a websocket with data from outside the the tornado app
Since sh.read is blocking, you'll need to run it in an executor. To then notify clients in the main thread, you'll need to use IOLoop.add_callback (safe to call from any thread). This also means the reader method becomes a regular sync method.
Example:
from concurrent.futures import ThreadPoolExecutor
import functools
from tornado import web, websocket, ioloop
log = print
class IndexHandler(web.RequestHandler):
def get(self):
self.write("""<html>
<textarea cols="30" rows="10" id="output">%s</textarea><br />
start<br />
stop<br />
<iframe name="f" width="100" height="30"></iframe>
<script>
ws = new WebSocket("ws://localhost:8888/stream");
out_el = document.getElementById("output");
function log(data) {out_el.value = data + "\\n" + out_el.value;}
ws.onmessage = function (ev) {log(ev.data);}
</script>""" % "\n".join(map(str, reversed(self.application.read_data))))
class StartHandler(web.RequestHandler):
def get(self):
self.application.start_reader()
self.write("Started")
class StopHandler(web.RequestHandler):
def get(self):
self.application.stop_reader()
self.write("Stopped")
class WebSocketHandler(websocket.WebSocketHandler):
connections = set()
def open(self):
WebSocketHandler.connections.add(self)
def on_close(self):
if self in WebSocketHandler.connections:
WebSocketHandler.connections.remove(self)
class WebApplication(web.Application):
def __init__(self, autostart=False):
handlers = [
(r"/", IndexHandler),
(r"/start", StartHandler),
(r"/stop", StopHandler),
(r'/stream', WebSocketHandler),
]
web.Application.__init__(self, handlers)
self._reader_executor = ThreadPoolExecutor(1)
self._keep_reading = None
self.read_data = []
if autostart:
self.start_reader()
def start_reader(self):
if not self._keep_reading:
self._keep_reading = True
loop = ioloop.IOLoop.current()
self._reader_future = loop.run_in_executor(self._reader_executor, functools.partial(self.reader, loop))
def stop_reader(self):
if self._keep_reading:
self._keep_reading = False
self._reader_future.cancel()
def notify_clients(self, data=None):
for con in WebSocketHandler.connections:
try:
con.write_message("{}".format(data))
except Exception as ex:
log("error sending to {}".format(con))
def reader(self, main_loop):
import random
import time
while self._keep_reading:
time.sleep(1 + random.random()) # simulate read - block for some time
data = random.getrandbits(32)
print("reader: data={}".format(data))
if data:
main_loop.add_callback(self.notify_clients, data)
self.read_data.append(data)
time.sleep(0.1)
if __name__ == "__main__":
app = WebApplication(True)
app.listen(8888)
loop = ioloop.IOLoop.current()
try:
loop.start()
except KeyboardInterrupt as ex:
app.stop_reader()
for con in WebSocketHandler.connections:
con.close()
loop.stop()

pyqt5 QThread with SOAP Zeep Client

I am working on a simple application with GUI which connect to a server via SOAP and request some data, this data is returned in XML format
I was able to run in my application successfully but due to threading, GUI is freezes till the complete SOAP request is finished and returned its value
now I am trying to run my application into threading, I created a Thread which to first check and verify the SOAP connection if it is successful or not
Connection Verification
class WorkerThread(QThread):
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
self.session = Session()
self.session.verify = False
self.cucmurl = 'https://URL'
self.session.auth = HTTPBasicAuth(user, pass)
self.cache = SqliteCache(path='/tmp/sqlite.db', timeout=10)
self.trself.clientansport = Transport(session=self.session, cache=self.cache)
self.client = Client(wsdl, transport=self.transport, strict=False)
the above work fine to verify the connection, but I want to use the self.client later in my code in order to start initiating SOAP connection to severs
class MainAPP(QTabWidget, UI_File):
def __init__(self, parent=None):
def getinfor(self):
output_2 = self.client.getinfor('')
the function getinfor should be able to use the self.client from the WorkerThread.
any idea how to accomplish this
You can emit the client through a signal from the worker thread and set it in the main window.
class WorkerThread(QThread):
client_signal = pyqtSignal(object)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
# code here
self.client = Client(wsdl, transport=self.transport, strict=False)
self.client_signal.emit(self.client)
class MainApp(QTabWidget, UI_File):
def __init__(self):
self.client = None
def set_client(self, client):
self.client = client
def setup_thread(self):
self.worker_thread = WorkerThread()
self.worker_thread.client_signal.connect(self.set_client)

Resources