Issue
I tried to execute the following example Python code in Jupyter Notebook v7.0.6:
https://xrpl-py.readthedocs.io/en/stable/source/snippets.html
from xrpl.clients import JsonRpcClient
from xrpl.models import Ledger, Tx
# References
# - https://xrpl.org/look-up-transaction-results.html
# - https://xrpl.org/parallel-networks.html#parallel-networks
# - https://xrpl.org/tx.html
# Create a client to connect to the main network
client = JsonRpcClient("https://xrplcluster.com/")
# Create a Ledger request and have the client call it
ledger_request = Ledger(ledger_index="validated", transactions=True)
ledger_response = client.request(ledger_request)
The code fails on the last line with the following error:
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/genericpath.py:77: RuntimeWarning: coroutine 'JsonRpcBase.request_impl' was never awaited
m = tuple(map(os.fspath, m))
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/genericpath.py:77: RuntimeWarning: coroutine 'WebsocketClient.request_impl' was never awaited
m = tuple(map(os.fspath, m))
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[47], line 2
1 ledger_request = Ledger(ledger_index="validated", transactions=True)
----> 2 ledger_response = client.request(ledger_request)
3 #ledger_response2 = client2.request(ledger_request)
4
5 #print(ledger_response)
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/xrpl/clients/sync_client.py:28, in SyncClient.request(self, request)
18 def request(self: SyncClient, request: Request) -> Response:
19 """
20 Makes a request with this client and returns the response.
21
(...)
26 The Response for the given Request.
27 """
---> 28 return asyncio.run(self.request_impl(request))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/runners.py:33, in run(main, debug)
9 """Execute the coroutine and return the result.
10
11 This function runs the passed coroutine, taking care of
(...)
30 asyncio.run(main())
31 """
32 if events._get_running_loop() is not None:
---> 33 raise RuntimeError(
34 "asyncio.run() cannot be called from a running event loop")
36 if not coroutines.iscoroutine(main):
37 raise ValueError("a coroutine was expected, got {!r}".format(main))
RuntimeError: asyncio.run() cannot be called from a running event loop
Note the same error occurs if the client was a Websocketclient:
from xrpl.clients import WebsocketClient
I see many posts regarding the same error on SO but I am not the author of xrpl-py and can't make the appropriate changes.
The solution offered is as follows:
asyncio.run error when using Jupyter Notebook
Error message when using a solution offered:
In [15]: import asyncio
...: from xrpl.clients import JsonRpcClient
...: from xrpl.models import Ledger
...:
In [16]: async def fetch_ledger_data():
...: client = JsonRpcClient("https://s1.ripple.com:51234")
...:
...: ledger_request = Ledger(ledger_index="validated", transactions=True)
...:
...: ledger_response = await client.request(ledger_request)
...:
...: return ledger_response
...:
In [17]: run -m fetch_ledger_data
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[17], line 1
----> 1 get_ipython().run_line_magic('run', '-m fetch_ledger_data')
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/IPython/core/interactiveshell.py:2456, in InteractiveShell.run_line_magic(self, magic_name, line, _stack_depth)
2454 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2455 with self.builtin_trap:
-> 2456 result = fn(*args, **kwargs)
2458 # The code below prevents the output from being displayed
2459 # when using magics with decorator @output_can_be_silenced
2460 # when the last Python token in the expression is a ';'.
2461 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/IPython/core/magics/execution.py:708, in ExecutionMagics.run(self, parameter_s, runner, file_finder)
706 if "m" in opts:
707 modulename = opts["m"][0]
--> 708 modpath = find_mod(modulename)
709 if modpath is None:
710 msg = '%r is not a valid modulename on sys.path'%modulename
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/IPython/utils/module_paths.py:62, in find_mod(module_name)
40 """
41 Find module `module_name` on sys.path, and return the path to module `module_name`.
42
(...)
59 depending on above conditions.
60 """
61 spec = importlib.util.find_spec(module_name)
---> 62 module_path = spec.origin
63 if module_path is None:
64 if spec.loader in sys.meta_path:
AttributeError: 'NoneType' object has no attribute 'origin'
UPDATE-2: This is the error message I get using the updated solution. At this point I am wondering whether the xrpl-py library can even be used with IPython (Jupyter Notebooks).
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[76], line 1
----> 1 response = await fetch_ledger_data()
Cell In[75], line 8, in fetch_ledger_data()
6 client = JsonRpcClient("https://s1.ripple.com:51234")
7 ledger_request = Ledger(ledger_index="validated", transactions=True)
----> 8 ledger_response = await client.request(ledger_request)
9 return ledger_response
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/xrpl/clients/sync_client.py:28, in SyncClient.request(self, request)
18 def request(self: SyncClient, request: Request) -> Response:
19 """
20 Makes a request with this client and returns the response.
21
(...)
26 The Response for the given Request.
27 """
---> 28 return asyncio.run(self.request_impl(request))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/runners.py:33, in run(main, debug)
9 """Execute the coroutine and return the result.
10
11 This function runs the passed coroutine, taking care of
(...)
30 asyncio.run(main())
31 """
32 if events._get_running_loop() is not None:
---> 33 raise RuntimeError(
34 "asyncio.run() cannot be called from a running event loop")
36 if not coroutines.iscoroutine(main):
37 raise ValueError("a coroutine was expected, got {!r}".format(main))
RuntimeError: asyncio.run() cannot be called from a running event loop
Solution
Well, the problem is within an already running event loop, it's common thing when you're running code in the env like Jupyter Notebook, and the problem within that is that it already has an event loop running in the background - therefore asyncio.run()
itself is made to run a coroutine in a fresh event loop, so that means it can't be used if there's already an event loop in progress...
Now, I know that xrpl-py
library functions are async
, you will need to run them in an async context, so on Jupyter notebook - by using %run
to handle this. Your approach would be:
- Define an async function
- Use %run to run the async func
Something like this should be working fine:
import asyncio
from xrpl.clients import JsonRpcClient
from xrpl.models import Ledger
async def fetch_ledger_data():
client = JsonRpcClient("https://xrplcluster.com/")
ledger_request = Ledger(ledger_index="validated", transactions=True)
ledger_response = await client.request(ledger_request)
return ledger_response
# To run it you'd do it like this:
# %run -m fetch_ledger_data
UPDATE 1:
Okay, since I now got a little bit of clue of what's happening here, let's re-arange the approach, as I think I confused OP with %run
command. The error you get, while using %run -m fetch_ledger_data
is originating by cause that Jupyter itself is trying to access the module named fetch_ledger_data
- but it can't (it doesn't exist as a separate module). Therefore or should I say: "that being said", %run
- command is used to execute python scripts, and not functions defined.
To address issue and provide more tailored up answer, in order for you to execute asynchronous
code, you should be using await
keyword directly in a notebook cell.
What is Notebook Cell.
Therefore, define async
func, as we did before, then you place this in a cell and execute it to define the function.
import asyncio
from xrpl.clients import JsonRpcClient
from xrpl.models import Ledger
async def fetch_ledger_data():
client = JsonRpcClient("https://xrplcluster.com/")
ledger_request = Ledger(ledger_index="validated", transactions=True)
ledger_response = await client.request(ledger_request)
return ledger_response
After that, in a new cell, you will directly await
the function that we just defined, why? The reason is simple, this way you will be running the async
function and since you expect some result you will be waiting for it.
# Execute the function and wait for the response
response = await fetch_ledger_data()
print(response)
By this, your async
function, you should be able to interact with xrpl
library, without running into problems with the asyncio
related errors.
When it comes to AttributeError
which you mentioned, it's more likely to be an issue which is not related to asyncio
and it might indicate a problem with the library or network request. (I can't really help here, I would need more context).
NEW UPDATE:
I got this running by usage of nest_asyncio
, you executed the following in new cell:
import nest_asyncio
nest_asyncio.apply()
You will have to update the code above to this:
async def fetch_ledger_data():
client = JsonRpcClient("https://xrplcluster.com/")
ledger_request = Ledger(ledger_index="validated", transactions=True)
ledger_response = client.request(ledger_request) # Removed 'await'
return ledger_response
Becasue the client.request
method is not designed to be awaited, you should call it without the await keyword.
Then you attempt this:
response = await fetch_ledger_data()
print(response)
Response Summary (which I got):
- Status: SUCCESS
- Ledger Index: 85408465
- Ledger Hash: [REDACTED]
- Total Coins: 99,987,960,274,971,725
- Close Time (UTC): 2024-Jan-20 15:53:40.000000000
- Transactions Included: [List of transaction hashes redacted for privacy]
Btw. I don't say that this is perfect solution, but it indeed does get stuff running.
Answered By - str1ng
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.