問題描述
當 gunicorn / celery 服務重新啟動時,Django 中有沒有辦法只執行一次 python 代碼? (Is there a way in Django to execute some python code only once when gunicorn / celery services are getting restarted?)
我的 Django 應用程序包含基於 celery 的任務,每次執行時都會從 SFTP 服務器下載某些文件。到現在為止,每次作業開始時我都會創建一個 SFTP 連接,並在作業結束時關閉連接。但是它是如何導致代碼中的文件描述符錯誤的(打開了太多的 SFTP 連接)。我正在考慮通過單例類建立 SFTP 連接,以便只建立一個 SFTP 連接,並且僅在我啟動 gunicorn/celery 服務時建立。
有沒有辦法我可以執行python代碼僅在應用程序啟動或重新啟動時一次創建SFTP連接?並且它關閉了服務停止了嗎?
參考解法
方法 1:
You can use global variables. Create a module sftp.py
sftp_connection = None
def create_sftp_connection():
...
...
return sftp_connection
def get_sftp_connection():
global sftp_connection
if not sftp_connection:
sftp_connection = create_sftp_connection()
return sftp_connection
Then in all the usages, import get_sftp_connection
and use
sftp_connection = get_sftp_connection()
...
方法 2:
Singleton class
class Singleton:
def __init__(self, klass):
self.klass = klass
self.instance = None
def __call__(self, *args, **kwds):
if self.instance is None:
self.instance = self.klass(*args, **kwds)
return self.instance
@Singleton
class SFTP_SINGLETON(object):
def __init__(self, hostname=None, username=None, password=None, port=22, default_path=None):
self._hostname = hostname
self._username = username
self._Password = password
self._sftp = None
self._port = port
self._default_path = default_path
self._sftp_live = False
self._transport = self._start_transport()
def _start_transport(self):
try:
self._transport = paramiko.Transport((self._hostname, self._port))
self._transport.connect(username=self._username, password=self._Password)
logger.info(" connected to {} : {}".format(self._hostname, self._port))
return self._transport
except (AttributeError, socket.gaierror) as e:
# couldn't connect
logger.info(" exception in establish_connection : %s ", e)
raise ConnectionException(self._hostname, self._port)
def connect(self):
"""Establish the SFTP connection."""
if not self._sftp_live:
self._sftp = paramiko.SFTPClient.from_transport(self._transport)
# if self._default_path is not None:
# self._sftp.chdir(self._default_path)
self._sftp_live = True
def close(self):
"""Closes the connection and cleans up."""
# Close SFTP Connection.
if self._sftp_live:
self._sftp.close()
self._sftp_live = False
# Close the SSH Transport.
if self._transport:
self._transport.close()
self._transport = None
(by Rohit Ranjan、vestronge、Lalit Suthar)