The python library json-stream likely does exactly what you are looking for. The request is a little ambiguous how you expect the final product to look, and I believe all the decorator parts likely add complexity to this that may not be required to accomplish what you describe.
To stream your data to the file you simply need to rewrite your function that outputs its parts to return json_stream.streamable_list or json_stream.streamable_dict objects and then everything else works without much alteration.
Depending on what the line "appending the value of out['fromdata'] for each output of the generator" means, I have 3 solutions for you.
- If you mean that literally, the json object is created, then subsequent
out['fromdata'] is appended to the previous fromdata field, it creates a heterogenous list with some values and some lists of values, and that is shown by the function streamable_func_literal.
- If you mean that each value of
out['fromdata'] is appended to a list, it creates a list of lists with each of their values, and that is shown by the function streamable_func_adjusted_append.
- If you mean that each value of
out['fromdata'] is extended onto the first one's values, it creates a list with all the values from all fromdata in it, and that is shown by the function streamable_func_adjusted_extend.
The func function is a direct copy of the example json you provided. If the real data is very different from that, you may need to adjust the appropriate streamable_func_* to match it. All the logic here is taken almost directly from the json-stream documentation's examples on pypi.
import json
import json_stream
def func():
for i in range(10):
out = {
'param0': 'somevalue',
'param1': {'someotherparams': 'somevalue'},
'fromdata': [0, 1, 2, i]
}
yield out
def streamable_func_literal():
# Define a function to stream the 'fromdata` field
def _fromdata_only():
func_generator = func()
for item_num, item in enumerate(func_generator):
# For the first call, create a list with each value in it
if item_num == 0:
for value in item['fromdata']:
yield value
# For each subsequent call, append the whole return value to the first one
else:
yield item['fromdata']
# Retrieve only the first entry, subsequent calls will be handled by the subfunction
entry = next(func())
# Replace the list in the 'fromdata' block with the streaming version defined above
entry['fromdata'] = json_stream.streamable_list(_fromdata_only())
# Yield each component of the parent dict
for key, value in entry.items():
yield key, value
def streamable_func_adjusted_append():
# Define a function to stream the 'fromdata` field
def _fromdata_only():
func_generator = func()
for item in func_generator:
# For each call, a list is returned creating a list of lists
yield item['fromdata']
# Retrieve only the first entry, subsequent calls will be handled by the subfunction
entry = next(func())
# Replace the list in the 'fromdata' block with the streaming version defined above
entry['fromdata'] = json_stream.streamable_list(_fromdata_only())
# Yield each component of the parent dict
for key, value in entry.items():
yield key, value
def streamable_func_adjusted_extend():
# Define a function to stream the 'fromdata` field
def _fromdata_only():
func_generator = func()
for item in func_generator:
# For each call, the values are appended to the list, creating one large list with all values
for value in item['fromdata']:
yield value
# Retrieve only the first entry, subsequent calls will be handled by the subfunction
entry = next(func())
# Replace the list in the 'fromdata' block with the streaming version defined above
entry['fromdata'] = json_stream.streamable_list(_fromdata_only())
# Yield each component of the parent dict
for key, value in entry.items():
yield key, value
for streamable_func in [
streamable_func_literal,
streamable_func_adjusted_append,
streamable_func_adjusted_extend
]:
data = json_stream.streamable_dict(streamable_func())
print(f'{streamable_func.__name__:<35}', json.dumps(data))
Which produces the following console:
streamable_func_literal {"param0": "somevalue", "param1": {"someotherparams": "somevalue"}, "fromdata": [0, 1, 2, 0, [0, 1, 2, 1], [0, 1, 2, 2], [0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 2, 6], [0, 1, 2, 7], [0, 1, 2, 8], [0, 1, 2, 9]]}
streamable_func_adjusted_append {"param0": "somevalue", "param1": {"someotherparams": "somevalue"}, "fromdata": [[0, 1, 2, 0], [0, 1, 2, 1], [0, 1, 2, 2], [0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 2, 6], [0, 1, 2, 7], [0, 1, 2, 8], [0, 1, 2, 9]]}
streamable_func_adjusted_extend {"param0": "somevalue", "param1": {"someotherparams": "somevalue"}, "fromdata": [0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 3, 0, 1, 2, 4, 0, 1, 2, 5, 0, 1, 2, 6, 0, 1, 2, 7, 0, 1, 2, 8, 0, 1, 2, 9]}
Let me know if you have any questions, or if the outputs don't quite match what you are expecting and I'll be glad to update it if I can.
return decoratorfor? Where are you returning it from?minimal working codewhich uses this decorator. And use some fake data, and show expected result for these data.