@@ -42,16 +42,16 @@ use pyo3::exceptions::PyValueError;
4242use pyo3:: prelude:: * ;
4343use pyo3:: pybacked:: PyBackedStr ;
4444use pyo3:: types:: { PyCapsule , PyList , PyTuple , PyTupleMethods } ;
45- use tokio:: task:: JoinHandle ;
4645
4746use crate :: catalog:: PyTable ;
48- use crate :: errors:: { py_datafusion_err, to_datafusion_err , PyDataFusionError } ;
47+ use crate :: errors:: { py_datafusion_err, PyDataFusionError } ;
4948use crate :: expr:: sort_expr:: to_sort_expressions;
5049use crate :: physical_plan:: PyExecutionPlan ;
5150use crate :: record_batch:: PyRecordBatchStream ;
5251use crate :: sql:: logical:: PyLogicalPlan ;
5352use crate :: utils:: {
54- get_tokio_runtime, is_ipython_env, py_obj_to_scalar_value, validate_pycapsule, wait_for_future,
53+ get_tokio_runtime, is_ipython_env, py_obj_to_scalar_value, spawn_and_wait, validate_pycapsule,
54+ wait_for_future,
5555} ;
5656use crate :: {
5757 errors:: PyDataFusionResult ,
@@ -880,11 +880,8 @@ impl PyDataFrame {
880880 requested_schema : Option < Bound < ' py , PyCapsule > > ,
881881 ) -> PyDataFusionResult < Bound < ' py , PyCapsule > > {
882882 // execute query lazily using a stream
883- let rt = & get_tokio_runtime ( ) . 0 ;
884883 let df = self . df . as_ref ( ) . clone ( ) ;
885- let fut: JoinHandle < datafusion:: common:: Result < SendableRecordBatchStream > > =
886- rt. spawn ( async move { df. execute_stream ( ) . await } ) ;
887- let stream = wait_for_future ( py, async { fut. await . map_err ( to_datafusion_err) } ) ???;
884+ let stream = spawn_and_wait ( py, async move { df. execute_stream ( ) . await } ) ?;
888885
889886 // Determine the schema and handle optional projection
890887 let stream_schema = stream. schema ( ) ;
@@ -911,24 +908,14 @@ impl PyDataFrame {
911908 }
912909
913910 fn execute_stream ( & self , py : Python ) -> PyDataFusionResult < PyRecordBatchStream > {
914- // create a Tokio runtime to run the async code
915- let rt = & get_tokio_runtime ( ) . 0 ;
916911 let df = self . df . as_ref ( ) . clone ( ) ;
917- let fut: JoinHandle < datafusion:: common:: Result < SendableRecordBatchStream > > =
918- rt. spawn ( async move { df. execute_stream ( ) . await } ) ;
919- let stream = wait_for_future ( py, async { fut. await . map_err ( to_datafusion_err) } ) ???;
912+ let stream = spawn_and_wait ( py, async move { df. execute_stream ( ) . await } ) ?;
920913 Ok ( PyRecordBatchStream :: new ( stream) )
921914 }
922915
923916 fn execute_stream_partitioned ( & self , py : Python ) -> PyResult < Vec < PyRecordBatchStream > > {
924- // create a Tokio runtime to run the async code
925- let rt = & get_tokio_runtime ( ) . 0 ;
926917 let df = self . df . as_ref ( ) . clone ( ) ;
927- let fut: JoinHandle < datafusion:: common:: Result < Vec < SendableRecordBatchStream > > > =
928- rt. spawn ( async move { df. execute_stream_partitioned ( ) . await } ) ;
929- let stream = wait_for_future ( py, async { fut. await . map_err ( to_datafusion_err) } ) ?
930- . map_err ( py_datafusion_err) ?
931- . map_err ( py_datafusion_err) ?;
918+ let stream = spawn_and_wait ( py, async move { df. execute_stream_partitioned ( ) . await } ) ?;
932919
933920 Ok ( stream. into_iter ( ) . map ( PyRecordBatchStream :: new) . collect ( ) )
934921 }
@@ -1025,7 +1012,7 @@ impl Iterator for ArrowStreamReader {
10251012
10261013 fn next ( & mut self ) -> Option < Self :: Item > {
10271014 let rt = & get_tokio_runtime ( ) . 0 ;
1028- match rt. block_on ( self . stream . next ( ) ) {
1015+ match rt. block_on ( crate :: record_batch :: pull_next_batch ( & mut self . stream ) ) {
10291016 Some ( Ok ( batch) ) => {
10301017 let batch = if self . project {
10311018 match record_batch_into_schema ( batch, self . schema . as_ref ( ) ) {
0 commit comments