Issue
I am trying to run a coroutine which gets data on a button click. It uses aiohttp
to get the data. The button is decorated with @asyncSlot()
from qasync
However, when I click the button, nothing happens, not even a print statement. I do not think the asyncio examples examples match my use case. I have tried moving when asyncio runs around to see if that helps. I am a little stumped as I get no errors to work with. Why is my function not running?
My code:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.container = QWidget() # Controls container widget.
self.controlsLayout = QVBoxLayout()
# -- Search bar and settings button
self.search_layout = QHBoxLayout()
self.search_bar = QLineEdit()
self.search_button = QPushButton("Search")
self.search_button.clicked.connect(self.update_data) # search by entered text
self.search_layout.addWidget(self.search_button)
self.controlsLayout.addLayout(self.search_layout)
# Our tab container with adjustable number of tabs
self.tab_container = TabContainer()
# Add out tabs widget
self.controlsLayout.addWidget(self.tab_container)
self.container.setLayout(self.controlsLayout)
self.setCentralWidget(self.container
@asyncSlot()
async def update_data(self):
stock_tickers = self.search_bar.text()
print("Entered tickers: ", stock_tickers)
short_interest = asyncio.create_task(self.setup_data(stock))
short_interest = await short_interest
print('SHORT INTEREST:', short_interest)
# Make a table in a new tab here
# ..............................
async def setup_data(self, stock):
short_interest = await get_data(stock) # this function is our main coroutine
# process the data here ...... as previous method return json
async def main():
app = QApplication(sys.argv)
loop = qasync.QEventLoop(app)
asyncio.set_event_loop(loop)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())
if __name__ == '__main__':
asyncio.run(main())
where my get_data(stock)
, which we can think of as an basic aiohttp json call, is defined as
async def get_data(stock_ticker):
async with aiohttp.ClientSession() as session:
async with session.get('https://www.finra.org/finra-data/browse-catalog/equity-short-interest/data') as response:
cfruid = session.cookie_jar.filter_cookies('https://www.finra.org/')["__cfruid"].value
print("CFRUID", cfruid)
five_months_date = date.today() + relativedelta(months=-5)
headers = {
'authority': 'services-dynarep.ddwa.finra.org',
'accept': 'application/json, text/plain, */*',
'accept-language': 'en-US,en;q=0.6',
'content-type': 'application/json',
'cookie': f'XSRF-TOKEN={cfruid};',
'origin': 'https://www.finra.org',
'referer': 'https://www.finra.org/',
'x-xsrf-token': cfruid,
}
json_data = {
'fields': [
'settlementDate',
'issueName',
'symbolCode',
'marketClassCode',
'currentShortPositionQuantity',
'previousShortPositionQuantity',
'changePreviousNumber',
'changePercent',
'averageDailyVolumeQuantity',
'daysToCoverQuantity',
'revisionFlag',
],
'dateRangeFilters': [],
'domainFilters': [],
'compareFilters': [
{
'fieldName': 'symbolCode',
'fieldValue': 'GME',
'compareType': 'EQUAL',
},
{
'fieldName': 'settlementDate',
'fieldValue': str(five_months_date),
'compareType': 'GREATER',
},
],
'multiFieldMatchFilters': [],
'orFilters': [],
'aggregationFilter': None,
'sortFields': [
'-settlementDate',
'+issueName',
],
'limit': 50,
'offset': 0,
'delimiter': None,
'quoteValues': False,
}
async with session.post('https://services-dynarep.ddwa.finra.org/public/reporting/v2/data/group/OTCMarket/name/ConsolidatedShortInterest',
headers=headers, json=json_data) as response2:
short_interest_data = await response2.json()
return short_interest_data
I was able to have the coroutine work and return data in its own file by creating a task and awaiting it. I also tried using the loop
instead. What am I missing? Note, other regular methods work when the button is clicked so I know it is just asyncio that refuses to run.
Edit: It seems to hang at the beginning of the aiohttp
part not running the print statement I have within get_data
Solution
Using QThread seems to help with this
class DataWorker(QThread):
data_ready = Signal(dict)
def __init__(self, stock_ticker):
super().__init__()
self.stock_ticker = stock_ticker
async def get_data(self):
async with aiohttp.ClientSession() as session:
# ... Your existing async code to fetch data ...
self.data_ready.emit(short_interest_data)
def run(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.get_data())
class MainWindow(QMainWindow):
# your existing code
def update_data(self):
stock_ticker = self.search_bar.text()
print("Entered tickers: ", stock_ticker)
self.data_worker = DataWorker(stock_ticker)
self.data_worker.data_ready.connect(self.setup_data)
self.data_worker.start()
# other codes
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I can't verify whether this is completely correct, because your code does not look complete, but it seems that after this correction, you can use async functions.
Answered By - Sepu Ling
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.