質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

受付中

Pythonでreturnの後に処理を実行したい

sasaki0628
sasaki0628

総合スコア95

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

5回答

0グッド

0クリップ

349閲覧

投稿2022/12/01 06:58

編集2023/01/13 03:23
from rest_framework.views import APIView from rest_framework.response import Response import gc class test(APIView): def post(self,request,*args,**kwargs): __test = self.request.data['test'] return Response(__test) del __test gc.collect()

DjangoでAPIを作成しています。returnの後に使用しない変数のオブジェクトを削除してガベージコレクションをしたいのですが、どのような方法があるでしょうか。

▽追記
みなさま回答ありがとうございました。WEBサイトの作成でメモリが足りなくなり、pythonのガベージコレクションを行うことで解決しようとしていました。そのあと調査を続けたところ、ApacheとMySQLのチューニングを行うことにより、メモリ不足を解決することができました。質問の件について、私の実力ではベストアンサーを選ぶことができないため、1ヵ月ほど様子を見て、グッドの数が多い方をベストアンサーにして質問を閉めさせていただきます。ありがとうございました。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答5

2

returnの後にその関数内でなにかすることはできません。

使用しない変数のオブジェクトを削除

もし、そのオブジェクトが関数外で使われないのであれば、pythonが自動で消してくれるので不要です。
また、質問の「__test」が束縛されているオブジェクトは、returnで返しているので、もし消してしまうと受け取った側で使えなくなります。

ガベージコレクションをしたい

もし、どうしてもやりたいなら、returnの前にやることになるでしょう。
消したオブジェクトをちゃんと消すのが目的なら、前に書いたとおりです。

また、書いたとおりインタプリタが適切に実施してくれるので、プログラムから意識的にGCを呼ぶ必要は無いと思います。

投稿2022/12/01 07:10

TakaiY

総合スコア10458

otn😄を押しています
sasaki0628👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

decoratorを使うのが一番簡単だと思いました(処理を追いにくく悪評も多い気がしますが)。

コード

python

1import os 2import gc 3import psutil 4 5def print_memories(): 6 print(psutil.Process(os.getpid()).memory_info()) 7 8def gc_when_returned(func): 9 def wrapper(*args, **kwargs): 10 func(*args, **kwargs) 11 gc.collect() 12 print("gc collected.") 13 return wrapper 14 15def hoge(): 16 print("hoge()") 17 o = [x for x in range(1024 * 1024)] 18 print_memories() 19 20@gc_when_returned 21def hoge_with_gc(): 22 print("hoge_with_gc()") 23 o = [x for x in range(1024 * 1024)] 24 print_memories() 25 26print_memories() 27hoge() 28print_memories() 29hoge_with_gc() 30print_memories()

※psutilはpipで入れる必要があります

結果

うちの環境(ubuntu 20.04 python3.8.10)だと実行結果は以下のようになります。

text

1pmem(rss=12230656, vms=22401024, shared=6459392, text=2863104, lib=0, data=5971968, dirty=0) 2hoge() 3pmem(rss=54915072, vms=65384448, shared=6602752, text=2863104, lib=0, data=48955392, dirty=0) 4pmem(rss=12750848, vms=22605824, shared=6602752, text=2863104, lib=0, data=6176768, dirty=0) 5hoge_with_gc() 6pmem(rss=54648832, vms=68108288, shared=6602752, text=2863104, lib=0, data=51679232, dirty=0) 7gc collected. 8pmem(rss=20930560, vms=34029568, shared=6602752, text=2863104, lib=0, data=17600512, dirty=0)

今回の例を今回の環境で見ると、普通に戻っただけでも開放されているので、あまり期待した効果はないようです。他の環境(処理系/バージョン/プラットフォーム)でどうなるかは未知数なので、能動的なgc自体に意味がないかどうかは分かりません。

注意

gcは基本的に自動で行われますが、任意のタイミングで実施できます。個人的に考えている、能動的なgcの主な使用用途としては、大きなメモリを使った後長く忙しい処理が入るとき、その直前に確実にメモリを空けておきたいとか、メモリの少ない環境でこまめに手動でgcしておきたいとか(パラメータでも調整できるかも)、でしょうか。いずれにしても比較的負荷の高い作業なことに注意です。

投稿2022/12/06 05:12

dameo

総合スコア594

sasaki0628👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

「returnの後に使用しない変数のオブジェクト」をローカルな名前空間から削除したとしても、それはDjangoがクライアントにレスポンスとして返し終わるまでは必要なオブジェクトであり続けます。
関数の終了後にガベージコレクションをしたとしても、レスポンスに必要なオブジェクトである限りガベージコレクションで回収の対象になるはずがありません


また、これはX-Y問題であるように感じます。

質問のような考えを仮定するとしても、カベージコレクションに回収されなかった時に何か困ることが起きているのでしょうか?
その何か困ることの方を質問するべきです
何も困っていないのなら何もする必要はないし、何か困っているならその困っていることを解決する手段が知りたいはずだからです。(そして回答者は何もする必要はないことに回答はしたくないし、困っていることが解決する手段を回答したいのです)


Responseを返却し終わった後に処理をさせる方法を探してみましたが、request_finishedシグナルに応じて毎回ガベージコレクションを走らせるくらいしかなさそうでした。これですとすべてのリクエストの後にガベージコレクションが走ってまうので現実的ではなさそうという感想です。

あとはResponseを継承して終了後に何かを実行するという案もあります。
破棄したいものが特別扱いされるように__init__を共に実装すれば何かが解決するかもしれません。

どちらも何に困っているかが質問にない以上、直接の回答はできずアイディア止まりです。あしからず。

投稿2022/12/02 05:35

編集2022/12/02 05:41
quickquip

総合スコア10419

sasaki0628👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

contextlib.ExitStack を利用して、Golang の defer と同様な事ができます。
※ 今回の場合、test.defer() メソッド内での処理は不要なものかと思います。

python

1from contextlib import ExitStack 2import gc 3 4class Response(): 5 def __init__(self, arg): 6 self.arg = arg 7 8class test(): 9 def defer(self, local_vars, name): 10 del local_vars[f'_{__class__.__name__}{name}'] 11 gc.collect() 12 print('defer done') 13 14 def post(self,*args,**kwargs): 15 with ExitStack() as stack: 16 __test = [1, 'Response value'] 17 stack.callback(self.defer, locals(), '__test') 18 19 print('return from post') 20 return Response(__test) 21 22if __name__ == '__main__': 23 t = test() 24 ret = t.post() 25 print(ret.arg) 26 27# return from post 28# defer done 29# [1, 'Response value']

投稿2022/12/01 08:49

編集2022/12/01 09:27
melian

総合スコア16234

sasaki0628👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

python

1from rest_framework.views import APIView 2from rest_framework.response import Response 3import gc 4 5class test(APIView): 6 def post(self,request,*args,**kwargs): 7 8 __test = self.request.data['test'] 9 10 ret = Response(__test) 11 12 del __test 13 gc.collect() 14 return ret

ただし、ガベージコレクトは必要なときに走ってくれるので自分で走らせる意味は無いと思います。

投稿2022/12/01 07:12

編集2022/12/01 07:16
ozwk

総合スコア13048

sasaki0628👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。