We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use .comet.config file for CometLogger
## 🚀 Feature

When creating a CometML experiment normally, the API key will be read from the file `~/.comet.config` or from an environment variable if it isn't passed in directly. It would be nice if the `CometLogger` supported these uses as well.

### Motivation

Putting the API key in code is certainly a bad practice, and it's a pain to have to export it as an environment variable and then get its value in Python or else read it from the file manually. Adding this feature makes things more seamless compared to how people use CometML when not using PyTorch Lightning.

### Additional context

I have a [patch] written for this already; it only changes a few lines of code. From the template message when I went to create a PR, though, it seemed I should create an issue first. Let me know if you have thoughts about this.

(somewhat related - the REST API key is also [deprecated]; the normal API key should be used instead now. I didn't change that code, though, because I'm not sure if older versions of Comet would have any issues with that change.)

[patch]: https://github.com/PyTorchLightning/pytorch-lightning/compare/master...neighthan:master
[deprecated]: https://www.comet.ml/docs/python-sdk/advanced/#python-configuration

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pytorch_lightning/loggers/comet.py`
Content:
```
1 """
2 Comet
3 -----
4 """
5 
6 from argparse import Namespace
7 from typing import Optional, Dict, Union, Any
8 
9 try:
10     from comet_ml import Experiment as CometExperiment
11     from comet_ml import ExistingExperiment as CometExistingExperiment
12     from comet_ml import OfflineExperiment as CometOfflineExperiment
13     from comet_ml import BaseExperiment as CometBaseExperiment
14     try:
15         from comet_ml.api import API
16     except ImportError:  # pragma: no-cover
17         # For more information, see: https://www.comet.ml/docs/python-sdk/releases/#release-300
18         from comet_ml.papi import API  # pragma: no-cover
19 
20     _COMET_AVAILABLE = True
21 except ImportError:  # pragma: no-cover
22     CometExperiment = None
23     CometExistingExperiment = None
24     CometOfflineExperiment = None
25     CometBaseExperiment = None
26     API = None
27     _COMET_AVAILABLE = False
28 
29 
30 import torch
31 from torch import is_tensor
32 
33 from pytorch_lightning import _logger as log
34 from pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment
35 from pytorch_lightning.utilities.exceptions import MisconfigurationException
36 from pytorch_lightning.utilities import rank_zero_only
37 
38 
39 class CometLogger(LightningLoggerBase):
40     r"""
41     Log using `Comet.ml <https://www.comet.ml>`_. Install it with pip:
42 
43     .. code-block:: bash
44 
45         pip install comet-ml
46 
47     Comet requires either an API Key (online mode) or a local directory path (offline mode).
48 
49     **ONLINE MODE**
50 
51     Example:
52         >>> import os
53         >>> from pytorch_lightning import Trainer
54         >>> from pytorch_lightning.loggers import CometLogger
55         >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class
56         >>> comet_logger = CometLogger(
57         ...     api_key=os.environ.get('COMET_API_KEY'),
58         ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional
59         ...     save_dir='.',  # Optional
60         ...     project_name='default_project',  # Optional
61         ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional
62         ...     experiment_name='default'  # Optional
63         ... )
64         >>> trainer = Trainer(logger=comet_logger)
65 
66     **OFFLINE MODE**
67 
68     Example:
69         >>> from pytorch_lightning.loggers import CometLogger
70         >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class
71         >>> comet_logger = CometLogger(
72         ...     save_dir='.',
73         ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional
74         ...     project_name='default_project',  # Optional
75         ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional
76         ...     experiment_name='default'  # Optional
77         ... )
78         >>> trainer = Trainer(logger=comet_logger)
79 
80     Args:
81         api_key: Required in online mode. API key, found on Comet.ml
82         save_dir: Required in offline mode. The path for the directory to save local comet logs
83         workspace: Optional. Name of workspace for this user
84         project_name: Optional. Send your experiment to a specific project.
85             Otherwise will be sent to Uncategorized Experiments.
86             If the project name does not already exist, Comet.ml will create a new project.
87         rest_api_key: Optional. Rest API key found in Comet.ml settings.
88             This is used to determine version number
89         experiment_name: Optional. String representing the name for this particular experiment on Comet.ml.
90         experiment_key: Optional. If set, restores from existing experiment.
91     """
92 
93     def __init__(self,
94                  api_key: Optional[str] = None,
95                  save_dir: Optional[str] = None,
96                  workspace: Optional[str] = None,
97                  project_name: Optional[str] = None,
98                  rest_api_key: Optional[str] = None,
99                  experiment_name: Optional[str] = None,
100                  experiment_key: Optional[str] = None,
101                  **kwargs):
102 
103         if not _COMET_AVAILABLE:
104             raise ImportError('You want to use `comet_ml` logger which is not installed yet,'
105                               ' install it with `pip install comet-ml`.')
106         super().__init__()
107         self._experiment = None
108         self._save_dir = save_dir
109 
110         # Determine online or offline mode based on which arguments were passed to CometLogger
111         if api_key is not None:
112             self.mode = "online"
113             self.api_key = api_key
114         elif save_dir is not None:
115             self.mode = "offline"
116             self._save_dir = save_dir
117         else:
118             # If neither api_key nor save_dir are passed as arguments, raise an exception
119             raise MisconfigurationException("CometLogger requires either api_key or save_dir during initialization.")
120 
121         log.info(f"CometLogger will be initialized in {self.mode} mode")
122 
123         self.workspace = workspace
124         self.project_name = project_name
125         self.experiment_key = experiment_key
126         self._kwargs = kwargs
127 
128         if rest_api_key is not None:
129             # Comet.ml rest API, used to determine version number
130             self.rest_api_key = rest_api_key
131             self.comet_api = API(self.rest_api_key)
132         else:
133             self.rest_api_key = None
134             self.comet_api = None
135 
136         if experiment_name:
137             self.experiment.set_name(experiment_name)
138         self._kwargs = kwargs
139 
140     @property
141     @rank_zero_experiment
142     def experiment(self) -> CometBaseExperiment:
143         r"""
144         Actual Comet object. To use Comet features in your
145         :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.
146 
147         Example::
148 
149             self.logger.experiment.some_comet_function()
150 
151         """
152         if self._experiment is not None:
153             return self._experiment
154 
155         if self.mode == "online":
156             if self.experiment_key is None:
157                 self._experiment = CometExperiment(
158                     api_key=self.api_key,
159                     workspace=self.workspace,
160                     project_name=self.project_name,
161                     **self._kwargs
162                 )
163                 self.experiment_key = self._experiment.get_key()
164             else:
165                 self._experiment = CometExistingExperiment(
166                     api_key=self.api_key,
167                     workspace=self.workspace,
168                     project_name=self.project_name,
169                     previous_experiment=self.experiment_key,
170                     **self._kwargs
171                 )
172         else:
173             self._experiment = CometOfflineExperiment(
174                 offline_directory=self.save_dir,
175                 workspace=self.workspace,
176                 project_name=self.project_name,
177                 **self._kwargs
178             )
179 
180         return self._experiment
181 
182     @rank_zero_only
183     def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:
184         params = self._convert_params(params)
185         params = self._flatten_dict(params)
186         self.experiment.log_parameters(params)
187 
188     @rank_zero_only
189     def log_metrics(
190             self,
191             metrics: Dict[str, Union[torch.Tensor, float]],
192             step: Optional[int] = None
193     ) -> None:
194         assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'
195 
196         # Comet.ml expects metrics to be a dictionary of detached tensors on CPU
197         for key, val in metrics.items():
198             if is_tensor(val):
199                 metrics[key] = val.cpu().detach()
200 
201         self.experiment.log_metrics(metrics, step=step)
202 
203     def reset_experiment(self):
204         self._experiment = None
205 
206     @rank_zero_only
207     def finalize(self, status: str) -> None:
208         r"""
209         When calling ``self.experiment.end()``, that experiment won't log any more data to Comet.
210         That's why, if you need to log any more data, you need to create an ExistingCometExperiment.
211         For example, to log data when testing your model after training, because when training is
212         finalized :meth:`CometLogger.finalize` is called.
213 
214         This happens automatically in the :meth:`~CometLogger.experiment` property, when
215         ``self._experiment`` is set to ``None``, i.e. ``self.reset_experiment()``.
216         """
217         self.experiment.end()
218         self.reset_experiment()
219 
220     @property
221     def save_dir(self) -> Optional[str]:
222         return self._save_dir
223 
224     @property
225     def name(self) -> str:
226         return str(self.experiment.project_name)
227 
228     @property
229     def version(self) -> str:
230         return self.experiment.id
231 
232     def __getstate__(self):
233         state = self.__dict__.copy()
234         state["_experiment"] = None
235         return state
236
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pytorch_lightning/loggers/comet.py b/pytorch_lightning/loggers/comet.py
--- a/pytorch_lightning/loggers/comet.py
+++ b/pytorch_lightning/loggers/comet.py
@@ -16,8 +16,7 @@
     except ImportError:  # pragma: no-cover
         # For more information, see: https://www.comet.ml/docs/python-sdk/releases/#release-300
         from comet_ml.papi import API  # pragma: no-cover
-
-    _COMET_AVAILABLE = True
+    from comet_ml.config import get_config, get_api_key
 except ImportError:  # pragma: no-cover
     CometExperiment = None
     CometExistingExperiment = None
@@ -25,6 +24,8 @@
     CometBaseExperiment = None
     API = None
     _COMET_AVAILABLE = False
+else:
+    _COMET_AVAILABLE = True
 
 
 import torch
@@ -78,8 +79,11 @@
         >>> trainer = Trainer(logger=comet_logger)
 
     Args:
-        api_key: Required in online mode. API key, found on Comet.ml
-        save_dir: Required in offline mode. The path for the directory to save local comet logs
+        api_key: Required in online mode. API key, found on Comet.ml. If not given, this
+            will be loaded from the environment variable COMET_API_KEY or ~/.comet.config
+            if either exists.
+        save_dir: Required in offline mode. The path for the directory to save local
+            comet logs. If given, this also sets the directory for saving checkpoints.
         workspace: Optional. Name of workspace for this user
         project_name: Optional. Send your experiment to a specific project.
             Otherwise will be sent to Uncategorized Experiments.
@@ -88,6 +92,10 @@
             This is used to determine version number
         experiment_name: Optional. String representing the name for this particular experiment on Comet.ml.
         experiment_key: Optional. If set, restores from existing experiment.
+        offline: If api_key and save_dir are both given, this determines whether
+            the experiment will be in online or offline mode. This is useful if you use
+            save_dir to control the checkpoints directory and have a ~/.comet.config
+            file but still want to run offline experiments.
     """
 
     def __init__(self,
@@ -98,6 +106,7 @@
                  rest_api_key: Optional[str] = None,
                  experiment_name: Optional[str] = None,
                  experiment_key: Optional[str] = None,
+                 offline: bool = False,
                  **kwargs):
 
         if not _COMET_AVAILABLE:
@@ -105,10 +114,15 @@
                               ' install it with `pip install comet-ml`.')
         super().__init__()
         self._experiment = None
-        self._save_dir = save_dir
 
         # Determine online or offline mode based on which arguments were passed to CometLogger
-        if api_key is not None:
+        api_key = api_key or get_api_key(None, get_config())
+
+        if api_key is not None and save_dir is not None:
+            self.mode = "offline" if offline else "online"
+            self.api_key = api_key
+            self._save_dir = save_dir
+        elif api_key is not None:
             self.mode = "online"
             self.api_key = api_key
         elif save_dir is not None:
@@ -116,7 +130,9 @@
             self._save_dir = save_dir
         else:
             # If neither api_key nor save_dir are passed as arguments, raise an exception
-            raise MisconfigurationException("CometLogger requires either api_key or save_dir during initialization.")
+            raise MisconfigurationException(
+                "CometLogger requires either api_key or save_dir during initialization."
+            )
 
         log.info(f"CometLogger will be initialized in {self.mode} mode")

{"golden_diff": "diff --git a/pytorch_lightning/loggers/comet.py b/pytorch_lightning/loggers/comet.py\n--- a/pytorch_lightning/loggers/comet.py\n+++ b/pytorch_lightning/loggers/comet.py\n@@ -16,8 +16,7 @@\n     except ImportError:  # pragma: no-cover\n         # For more information, see: https://www.comet.ml/docs/python-sdk/releases/#release-300\n         from comet_ml.papi import API  # pragma: no-cover\n-\n-    _COMET_AVAILABLE = True\n+    from comet_ml.config import get_config, get_api_key\n except ImportError:  # pragma: no-cover\n     CometExperiment = None\n     CometExistingExperiment = None\n@@ -25,6 +24,8 @@\n     CometBaseExperiment = None\n     API = None\n     _COMET_AVAILABLE = False\n+else:\n+    _COMET_AVAILABLE = True\n \n \n import torch\n@@ -78,8 +79,11 @@\n         >>> trainer = Trainer(logger=comet_logger)\n \n     Args:\n-        api_key: Required in online mode. API key, found on Comet.ml\n-        save_dir: Required in offline mode. The path for the directory to save local comet logs\n+        api_key: Required in online mode. API key, found on Comet.ml. If not given, this\n+            will be loaded from the environment variable COMET_API_KEY or ~/.comet.config\n+            if either exists.\n+        save_dir: Required in offline mode. The path for the directory to save local\n+            comet logs. If given, this also sets the directory for saving checkpoints.\n         workspace: Optional. Name of workspace for this user\n         project_name: Optional. Send your experiment to a specific project.\n             Otherwise will be sent to Uncategorized Experiments.\n@@ -88,6 +92,10 @@\n             This is used to determine version number\n         experiment_name: Optional. String representing the name for this particular experiment on Comet.ml.\n         experiment_key: Optional. If set, restores from existing experiment.\n+        offline: If api_key and save_dir are both given, this determines whether\n+            the experiment will be in online or offline mode. This is useful if you use\n+            save_dir to control the checkpoints directory and have a ~/.comet.config\n+            file but still want to run offline experiments.\n     \"\"\"\n \n     def __init__(self,\n@@ -98,6 +106,7 @@\n                  rest_api_key: Optional[str] = None,\n                  experiment_name: Optional[str] = None,\n                  experiment_key: Optional[str] = None,\n+                 offline: bool = False,\n                  **kwargs):\n \n         if not _COMET_AVAILABLE:\n@@ -105,10 +114,15 @@\n                               ' install it with `pip install comet-ml`.')\n         super().__init__()\n         self._experiment = None\n-        self._save_dir = save_dir\n \n         # Determine online or offline mode based on which arguments were passed to CometLogger\n-        if api_key is not None:\n+        api_key = api_key or get_api_key(None, get_config())\n+\n+        if api_key is not None and save_dir is not None:\n+            self.mode = \"offline\" if offline else \"online\"\n+            self.api_key = api_key\n+            self._save_dir = save_dir\n+        elif api_key is not None:\n             self.mode = \"online\"\n             self.api_key = api_key\n         elif save_dir is not None:\n@@ -116,7 +130,9 @@\n             self._save_dir = save_dir\n         else:\n             # If neither api_key nor save_dir are passed as arguments, raise an exception\n-            raise MisconfigurationException(\"CometLogger requires either api_key or save_dir during initialization.\")\n+            raise MisconfigurationException(\n+                \"CometLogger requires either api_key or save_dir during initialization.\"\n+            )\n \n         log.info(f\"CometLogger will be initialized in {self.mode} mode\")\n", "issue": "Use .comet.config file for CometLogger\n## \ud83d\ude80 Feature\r\n\r\nWhen creating a CometML experiment normally, the API key will be read from the file `~/.comet.config` or from an environment variable if it isn't passed in directly. It would be nice if the `CometLogger` supported these uses as well.\r\n\r\n### Motivation\r\n\r\nPutting the API key in code is certainly a bad practice, and it's a pain to have to export it as an environment variable and then get its value in Python or else read it from the file manually. Adding this feature makes things more seamless compared to how people use CometML when not using PyTorch Lightning.\r\n\r\n### Additional context\r\n\r\nI have a [patch] written for this already; it only changes a few lines of code. From the template message when I went to create a PR, though, it seemed I should create an issue first. Let me know if you have thoughts about this.\r\n\r\n(somewhat related - the REST API key is also [deprecated]; the normal API key should be used instead now. I didn't change that code, though, because I'm not sure if older versions of Comet would have any issues with that change.)\r\n\r\n[patch]: https://github.com/PyTorchLightning/pytorch-lightning/compare/master...neighthan:master\r\n[deprecated]: https://www.comet.ml/docs/python-sdk/advanced/#python-configuration\n", "before_files": [{"content": "\"\"\"\nComet\n-----\n\"\"\"\n\nfrom argparse import Namespace\nfrom typing import Optional, Dict, Union, Any\n\ntry:\n    from comet_ml import Experiment as CometExperiment\n    from comet_ml import ExistingExperiment as CometExistingExperiment\n    from comet_ml import OfflineExperiment as CometOfflineExperiment\n    from comet_ml import BaseExperiment as CometBaseExperiment\n    try:\n        from comet_ml.api import API\n    except ImportError:  # pragma: no-cover\n        # For more information, see: https://www.comet.ml/docs/python-sdk/releases/#release-300\n        from comet_ml.papi import API  # pragma: no-cover\n\n    _COMET_AVAILABLE = True\nexcept ImportError:  # pragma: no-cover\n    CometExperiment = None\n    CometExistingExperiment = None\n    CometOfflineExperiment = None\n    CometBaseExperiment = None\n    API = None\n    _COMET_AVAILABLE = False\n\n\nimport torch\nfrom torch import is_tensor\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment\nfrom pytorch_lightning.utilities.exceptions import MisconfigurationException\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nclass CometLogger(LightningLoggerBase):\n    r\"\"\"\n    Log using `Comet.ml <https://www.comet.ml>`_. Install it with pip:\n\n    .. code-block:: bash\n\n        pip install comet-ml\n\n    Comet requires either an API Key (online mode) or a local directory path (offline mode).\n\n    **ONLINE MODE**\n\n    Example:\n        >>> import os\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import CometLogger\n        >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class\n        >>> comet_logger = CometLogger(\n        ...     api_key=os.environ.get('COMET_API_KEY'),\n        ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional\n        ...     save_dir='.',  # Optional\n        ...     project_name='default_project',  # Optional\n        ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional\n        ...     experiment_name='default'  # Optional\n        ... )\n        >>> trainer = Trainer(logger=comet_logger)\n\n    **OFFLINE MODE**\n\n    Example:\n        >>> from pytorch_lightning.loggers import CometLogger\n        >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class\n        >>> comet_logger = CometLogger(\n        ...     save_dir='.',\n        ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional\n        ...     project_name='default_project',  # Optional\n        ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional\n        ...     experiment_name='default'  # Optional\n        ... )\n        >>> trainer = Trainer(logger=comet_logger)\n\n    Args:\n        api_key: Required in online mode. API key, found on Comet.ml\n        save_dir: Required in offline mode. The path for the directory to save local comet logs\n        workspace: Optional. Name of workspace for this user\n        project_name: Optional. Send your experiment to a specific project.\n            Otherwise will be sent to Uncategorized Experiments.\n            If the project name does not already exist, Comet.ml will create a new project.\n        rest_api_key: Optional. Rest API key found in Comet.ml settings.\n            This is used to determine version number\n        experiment_name: Optional. String representing the name for this particular experiment on Comet.ml.\n        experiment_key: Optional. If set, restores from existing experiment.\n    \"\"\"\n\n    def __init__(self,\n                 api_key: Optional[str] = None,\n                 save_dir: Optional[str] = None,\n                 workspace: Optional[str] = None,\n                 project_name: Optional[str] = None,\n                 rest_api_key: Optional[str] = None,\n                 experiment_name: Optional[str] = None,\n                 experiment_key: Optional[str] = None,\n                 **kwargs):\n\n        if not _COMET_AVAILABLE:\n            raise ImportError('You want to use `comet_ml` logger which is not installed yet,'\n                              ' install it with `pip install comet-ml`.')\n        super().__init__()\n        self._experiment = None\n        self._save_dir = save_dir\n\n        # Determine online or offline mode based on which arguments were passed to CometLogger\n        if api_key is not None:\n            self.mode = \"online\"\n            self.api_key = api_key\n        elif save_dir is not None:\n            self.mode = \"offline\"\n            self._save_dir = save_dir\n        else:\n            # If neither api_key nor save_dir are passed as arguments, raise an exception\n            raise MisconfigurationException(\"CometLogger requires either api_key or save_dir during initialization.\")\n\n        log.info(f\"CometLogger will be initialized in {self.mode} mode\")\n\n        self.workspace = workspace\n        self.project_name = project_name\n        self.experiment_key = experiment_key\n        self._kwargs = kwargs\n\n        if rest_api_key is not None:\n            # Comet.ml rest API, used to determine version number\n            self.rest_api_key = rest_api_key\n            self.comet_api = API(self.rest_api_key)\n        else:\n            self.rest_api_key = None\n            self.comet_api = None\n\n        if experiment_name:\n            self.experiment.set_name(experiment_name)\n        self._kwargs = kwargs\n\n    @property\n    @rank_zero_experiment\n    def experiment(self) -> CometBaseExperiment:\n        r\"\"\"\n        Actual Comet object. To use Comet features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_comet_function()\n\n        \"\"\"\n        if self._experiment is not None:\n            return self._experiment\n\n        if self.mode == \"online\":\n            if self.experiment_key is None:\n                self._experiment = CometExperiment(\n                    api_key=self.api_key,\n                    workspace=self.workspace,\n                    project_name=self.project_name,\n                    **self._kwargs\n                )\n                self.experiment_key = self._experiment.get_key()\n            else:\n                self._experiment = CometExistingExperiment(\n                    api_key=self.api_key,\n                    workspace=self.workspace,\n                    project_name=self.project_name,\n                    previous_experiment=self.experiment_key,\n                    **self._kwargs\n                )\n        else:\n            self._experiment = CometOfflineExperiment(\n                offline_directory=self.save_dir,\n                workspace=self.workspace,\n                project_name=self.project_name,\n                **self._kwargs\n            )\n\n        return self._experiment\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        self.experiment.log_parameters(params)\n\n    @rank_zero_only\n    def log_metrics(\n            self,\n            metrics: Dict[str, Union[torch.Tensor, float]],\n            step: Optional[int] = None\n    ) -> None:\n        assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'\n\n        # Comet.ml expects metrics to be a dictionary of detached tensors on CPU\n        for key, val in metrics.items():\n            if is_tensor(val):\n                metrics[key] = val.cpu().detach()\n\n        self.experiment.log_metrics(metrics, step=step)\n\n    def reset_experiment(self):\n        self._experiment = None\n\n    @rank_zero_only\n    def finalize(self, status: str) -> None:\n        r\"\"\"\n        When calling ``self.experiment.end()``, that experiment won't log any more data to Comet.\n        That's why, if you need to log any more data, you need to create an ExistingCometExperiment.\n        For example, to log data when testing your model after training, because when training is\n        finalized :meth:`CometLogger.finalize` is called.\n\n        This happens automatically in the :meth:`~CometLogger.experiment` property, when\n        ``self._experiment`` is set to ``None``, i.e. ``self.reset_experiment()``.\n        \"\"\"\n        self.experiment.end()\n        self.reset_experiment()\n\n    @property\n    def save_dir(self) -> Optional[str]:\n        return self._save_dir\n\n    @property\n    def name(self) -> str:\n        return str(self.experiment.project_name)\n\n    @property\n    def version(self) -> str:\n        return self.experiment.id\n\n    def __getstate__(self):\n        state = self.__dict__.copy()\n        state[\"_experiment\"] = None\n        return state\n", "path": "pytorch_lightning/loggers/comet.py"}], "after_files": [{"content": "\"\"\"\nComet\n-----\n\"\"\"\n\nfrom argparse import Namespace\nfrom typing import Optional, Dict, Union, Any\n\ntry:\n    from comet_ml import Experiment as CometExperiment\n    from comet_ml import ExistingExperiment as CometExistingExperiment\n    from comet_ml import OfflineExperiment as CometOfflineExperiment\n    from comet_ml import BaseExperiment as CometBaseExperiment\n    try:\n        from comet_ml.api import API\n    except ImportError:  # pragma: no-cover\n        # For more information, see: https://www.comet.ml/docs/python-sdk/releases/#release-300\n        from comet_ml.papi import API  # pragma: no-cover\n    from comet_ml.config import get_config, get_api_key\nexcept ImportError:  # pragma: no-cover\n    CometExperiment = None\n    CometExistingExperiment = None\n    CometOfflineExperiment = None\n    CometBaseExperiment = None\n    API = None\n    _COMET_AVAILABLE = False\nelse:\n    _COMET_AVAILABLE = True\n\n\nimport torch\nfrom torch import is_tensor\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment\nfrom pytorch_lightning.utilities.exceptions import MisconfigurationException\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nclass CometLogger(LightningLoggerBase):\n    r\"\"\"\n    Log using `Comet.ml <https://www.comet.ml>`_. Install it with pip:\n\n    .. code-block:: bash\n\n        pip install comet-ml\n\n    Comet requires either an API Key (online mode) or a local directory path (offline mode).\n\n    **ONLINE MODE**\n\n    Example:\n        >>> import os\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import CometLogger\n        >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class\n        >>> comet_logger = CometLogger(\n        ...     api_key=os.environ.get('COMET_API_KEY'),\n        ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional\n        ...     save_dir='.',  # Optional\n        ...     project_name='default_project',  # Optional\n        ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional\n        ...     experiment_name='default'  # Optional\n        ... )\n        >>> trainer = Trainer(logger=comet_logger)\n\n    **OFFLINE MODE**\n\n    Example:\n        >>> from pytorch_lightning.loggers import CometLogger\n        >>> # arguments made to CometLogger are passed on to the comet_ml.Experiment class\n        >>> comet_logger = CometLogger(\n        ...     save_dir='.',\n        ...     workspace=os.environ.get('COMET_WORKSPACE'),  # Optional\n        ...     project_name='default_project',  # Optional\n        ...     rest_api_key=os.environ.get('COMET_REST_API_KEY'),  # Optional\n        ...     experiment_name='default'  # Optional\n        ... )\n        >>> trainer = Trainer(logger=comet_logger)\n\n    Args:\n        api_key: Required in online mode. API key, found on Comet.ml. If not given, this\n            will be loaded from the environment variable COMET_API_KEY or ~/.comet.config\n            if either exists.\n        save_dir: Required in offline mode. The path for the directory to save local\n            comet logs. If given, this also sets the directory for saving checkpoints.\n        workspace: Optional. Name of workspace for this user\n        project_name: Optional. Send your experiment to a specific project.\n            Otherwise will be sent to Uncategorized Experiments.\n            If the project name does not already exist, Comet.ml will create a new project.\n        rest_api_key: Optional. Rest API key found in Comet.ml settings.\n            This is used to determine version number\n        experiment_name: Optional. String representing the name for this particular experiment on Comet.ml.\n        experiment_key: Optional. If set, restores from existing experiment.\n        offline: If api_key and save_dir are both given, this determines whether\n            the experiment will be in online or offline mode. This is useful if you use\n            save_dir to control the checkpoints directory and have a ~/.comet.config\n            file but still want to run offline experiments.\n    \"\"\"\n\n    def __init__(self,\n                 api_key: Optional[str] = None,\n                 save_dir: Optional[str] = None,\n                 workspace: Optional[str] = None,\n                 project_name: Optional[str] = None,\n                 rest_api_key: Optional[str] = None,\n                 experiment_name: Optional[str] = None,\n                 experiment_key: Optional[str] = None,\n                 offline: bool = False,\n                 **kwargs):\n\n        if not _COMET_AVAILABLE:\n            raise ImportError('You want to use `comet_ml` logger which is not installed yet,'\n                              ' install it with `pip install comet-ml`.')\n        super().__init__()\n        self._experiment = None\n\n        # Determine online or offline mode based on which arguments were passed to CometLogger\n        api_key = api_key or get_api_key(None, get_config())\n\n        if api_key is not None and save_dir is not None:\n            self.mode = \"offline\" if offline else \"online\"\n            self.api_key = api_key\n            self._save_dir = save_dir\n        elif api_key is not None:\n            self.mode = \"online\"\n            self.api_key = api_key\n        elif save_dir is not None:\n            self.mode = \"offline\"\n            self._save_dir = save_dir\n        else:\n            # If neither api_key nor save_dir are passed as arguments, raise an exception\n            raise MisconfigurationException(\n                \"CometLogger requires either api_key or save_dir during initialization.\"\n            )\n\n        log.info(f\"CometLogger will be initialized in {self.mode} mode\")\n\n        self.workspace = workspace\n        self.project_name = project_name\n        self.experiment_key = experiment_key\n        self._kwargs = kwargs\n\n        if rest_api_key is not None:\n            # Comet.ml rest API, used to determine version number\n            self.rest_api_key = rest_api_key\n            self.comet_api = API(self.rest_api_key)\n        else:\n            self.rest_api_key = None\n            self.comet_api = None\n\n        if experiment_name:\n            self.experiment.set_name(experiment_name)\n        self._kwargs = kwargs\n\n    @property\n    @rank_zero_experiment\n    def experiment(self) -> CometBaseExperiment:\n        r\"\"\"\n        Actual Comet object. To use Comet features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_comet_function()\n\n        \"\"\"\n        if self._experiment is not None:\n            return self._experiment\n\n        if self.mode == \"online\":\n            if self.experiment_key is None:\n                self._experiment = CometExperiment(\n                    api_key=self.api_key,\n                    workspace=self.workspace,\n                    project_name=self.project_name,\n                    **self._kwargs\n                )\n                self.experiment_key = self._experiment.get_key()\n            else:\n                self._experiment = CometExistingExperiment(\n                    api_key=self.api_key,\n                    workspace=self.workspace,\n                    project_name=self.project_name,\n                    previous_experiment=self.experiment_key,\n                    **self._kwargs\n                )\n        else:\n            self._experiment = CometOfflineExperiment(\n                offline_directory=self.save_dir,\n                workspace=self.workspace,\n                project_name=self.project_name,\n                **self._kwargs\n            )\n\n        return self._experiment\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        self.experiment.log_parameters(params)\n\n    @rank_zero_only\n    def log_metrics(\n            self,\n            metrics: Dict[str, Union[torch.Tensor, float]],\n            step: Optional[int] = None\n    ) -> None:\n        assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'\n\n        # Comet.ml expects metrics to be a dictionary of detached tensors on CPU\n        for key, val in metrics.items():\n            if is_tensor(val):\n                metrics[key] = val.cpu().detach()\n\n        self.experiment.log_metrics(metrics, step=step)\n\n    def reset_experiment(self):\n        self._experiment = None\n\n    @rank_zero_only\n    def finalize(self, status: str) -> None:\n        r\"\"\"\n        When calling ``self.experiment.end()``, that experiment won't log any more data to Comet.\n        That's why, if you need to log any more data, you need to create an ExistingCometExperiment.\n        For example, to log data when testing your model after training, because when training is\n        finalized :meth:`CometLogger.finalize` is called.\n\n        This happens automatically in the :meth:`~CometLogger.experiment` property, when\n        ``self._experiment`` is set to ``None``, i.e. ``self.reset_experiment()``.\n        \"\"\"\n        self.experiment.end()\n        self.reset_experiment()\n\n    @property\n    def save_dir(self) -> Optional[str]:\n        return self._save_dir\n\n    @property\n    def name(self) -> str:\n        return str(self.experiment.project_name)\n\n    @property\n    def version(self) -> str:\n        return self.experiment.id\n\n    def __getstate__(self):\n        state = self.__dict__.copy()\n        state[\"_experiment\"] = None\n        return state\n", "path": "pytorch_lightning/loggers/comet.py"}]}