I made a function in 'hr.contract' that generate a payslip. But this payslip is used to simulate and calculate some salaries, so after create the payslip I must delete it.
Also, I made a function to print the payslip report, from the contract form. The problem is, when I click "print" button I create the payslip and return its report, but then I can't figure out a way to delete the payslip created.
def generate_report(self):
# I get this values from another methods,
# I put 1 and 20 just to avoid confution in the question.
run_id = 1
indicador_id = 20
payslip = self.generate_fake_nominee(run_id, self.employee_id.id, indicador_id, self.id)
report = payslip.print_nominee_report()
return report
I can't do stuff after the return, so any ideas?
Assuming payslip
is the only reference, it should be deleted when the function returns. If it holds resources that might not be cleaned up properly, either:
It should implement the context management protocol and a with
statement could be used:
with self.generate_fake_nominee(run_id, self.employee_id.id, indicador_id, self.id) as payslip:
return payslip.print_nominee_report()
or,
If you need to call some cleanup function manually, a finally
block can be used:
payslip = self.generate_fake_nominee(run_id, self.employee_id.id, indicador_id, self.id)
try:
return payslip.print_nominee_report()
finally:
payslip.cleanup_function()
To be clear, putting del payslip
in a finally
block would be completely pointless; the name will be unbound when the function returns anyway, so del
accomplishes nothing. Either the object bound to payslip
would be freed anyway (if it had no other aliases) or it wouldn't be free regardless (it's aliased elsewhere). payslip
is unbound when the function returns no matter what, and all del
does is make the unbinding explicit, which is slower and pointlessly verbose.
Update: It seems like the report
in your original code has a live dependency on the payslip
object, so you can't actually clean up the payslip
until the caller is done with the report. If that's the case, you have two options as well:
Figure out how to remove the live dependency, so report
is a standalone set of data (depends on code you haven't shown us, but this is the best solution when possible)
Use a finalizer tied to report
that preserves payslip
until report
is garbage collected, at which point it cleans it up, a la:
# At top of module
import weakref
def generate_report(self):
# I get this values from another methods,
# I put 1 and 20 just to avoid confution in the question.
run_id = 1
indicador_id = 20
payslip = self.generate_fake_nominee(run_id, self.employee_id.id, indicador_id, self.id)
report = payslip.print_nominee_report()
# Ensure cleanup_function is called when report is gc-ed
weakref.finalize(report, payslip.cleanup_function)
return report
This option isn't perfect; even on CPython with deterministic reference counting, if a reference cycle gets involved, even when you're done with report
it can take an arbitrary amount of time before the cycle collector is invoked and report
actually gets collected (and the cleanup function invoked). On non-CPython interpreters with true garbage collectors, this will happen even without reference cycles.