wandb 0.19.2__py3-none-any.whl → 0.19.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wandb/__init__.py +1 -1
- wandb/__init__.pyi +13 -3
- wandb/integration/metaflow/metaflow.py +7 -9
- wandb/sdk/wandb_init.py +240 -161
- wandb/sdk/wandb_run.py +10 -7
- wandb/sdk/wandb_settings.py +2 -27
- {wandb-0.19.2.dist-info → wandb-0.19.3.dist-info}/METADATA +1 -1
- {wandb-0.19.2.dist-info → wandb-0.19.3.dist-info}/RECORD +11 -11
- {wandb-0.19.2.dist-info → wandb-0.19.3.dist-info}/WHEEL +0 -0
- {wandb-0.19.2.dist-info → wandb-0.19.3.dist-info}/entry_points.txt +0 -0
- {wandb-0.19.2.dist-info → wandb-0.19.3.dist-info}/licenses/LICENSE +0 -0
wandb/__init__.py
CHANGED
wandb/__init__.pyi
CHANGED
@@ -103,7 +103,7 @@ if TYPE_CHECKING:
|
|
103
103
|
import wandb
|
104
104
|
from wandb.plot import CustomChart
|
105
105
|
|
106
|
-
__version__: str = "0.19.
|
106
|
+
__version__: str = "0.19.3"
|
107
107
|
|
108
108
|
run: Run | None
|
109
109
|
config: wandb_config.Config
|
@@ -651,7 +651,12 @@ def log(
|
|
651
651
|
run = wandb.init()
|
652
652
|
examples = []
|
653
653
|
for i in range(3):
|
654
|
-
pixels = np.random.randint(
|
654
|
+
pixels = np.random.randint(
|
655
|
+
low=0,
|
656
|
+
high=256,
|
657
|
+
size=(100, 100, 3),
|
658
|
+
dtype=np.uint8,
|
659
|
+
)
|
655
660
|
pil_image = PILImage.fromarray(pixels, mode="RGB")
|
656
661
|
image = wandb.Image(pil_image, caption=f"random field {i}")
|
657
662
|
examples.append(image)
|
@@ -666,7 +671,12 @@ def log(
|
|
666
671
|
|
667
672
|
run = wandb.init()
|
668
673
|
# axes are (time, channel, height, width)
|
669
|
-
frames = np.random.randint(
|
674
|
+
frames = np.random.randint(
|
675
|
+
low=0,
|
676
|
+
high=256,
|
677
|
+
size=(10, 3, 100, 100),
|
678
|
+
dtype=np.uint8,
|
679
|
+
)
|
670
680
|
run.log({"video": wandb.Video(frames, fps=4)})
|
671
681
|
```
|
672
682
|
|
@@ -328,15 +328,13 @@ def wandb_log(
|
|
328
328
|
if not isinstance(settings, wandb.sdk.wandb_settings.Settings):
|
329
329
|
settings = wandb.Settings()
|
330
330
|
|
331
|
-
settings.
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
run_job_type=coalesce(settings.run_job_type, current.step_name),
|
339
|
-
source=wandb.sdk.wandb_settings.Source.INIT,
|
331
|
+
settings.update_from_dict(
|
332
|
+
{
|
333
|
+
"run_group": coalesce(
|
334
|
+
settings.run_group, f"{current.flow_name}/{current.run_id}"
|
335
|
+
),
|
336
|
+
"run_job_type": coalesce(settings.run_job_type, current.step_name),
|
337
|
+
}
|
340
338
|
)
|
341
339
|
|
342
340
|
with wandb.init(settings=settings) as run:
|
wandb/sdk/wandb_init.py
CHANGED
@@ -14,6 +14,7 @@ import copy
|
|
14
14
|
import json
|
15
15
|
import logging
|
16
16
|
import os
|
17
|
+
import pathlib
|
17
18
|
import platform
|
18
19
|
import sys
|
19
20
|
import tempfile
|
@@ -48,14 +49,6 @@ from .wandb_settings import Settings
|
|
48
49
|
if TYPE_CHECKING:
|
49
50
|
from wandb.proto import wandb_internal_pb2 as pb
|
50
51
|
|
51
|
-
logger: wandb_setup.Logger | None = None # logger configured during wandb.init()
|
52
|
-
|
53
|
-
|
54
|
-
def _set_logger(log_object: wandb_setup.Logger | None) -> None:
|
55
|
-
"""Configure module logger."""
|
56
|
-
global logger
|
57
|
-
logger = log_object
|
58
|
-
|
59
52
|
|
60
53
|
def _huggingface_version() -> str | None:
|
61
54
|
if "transformers" in sys.modules:
|
@@ -115,9 +108,10 @@ def _handle_launch_config(settings: Settings) -> dict[str, Any]:
|
|
115
108
|
class _WandbInit:
|
116
109
|
_init_telemetry_obj: telemetry.TelemetryRecord
|
117
110
|
|
118
|
-
def __init__(self) -> None:
|
111
|
+
def __init__(self, wl: wandb_setup._WandbSetup) -> None:
|
112
|
+
self._wl = wl
|
113
|
+
|
119
114
|
self.kwargs = None
|
120
|
-
self.settings: Settings | None = None
|
121
115
|
self.sweep_config: dict[str, Any] = {}
|
122
116
|
self.launch_config: dict[str, Any] = {}
|
123
117
|
self.config: dict[str, Any] = {}
|
@@ -125,7 +119,6 @@ class _WandbInit:
|
|
125
119
|
self.backend: Backend | None = None
|
126
120
|
|
127
121
|
self._teardown_hooks: list[TeardownHook] = []
|
128
|
-
self._wl = wandb.setup()
|
129
122
|
self.notebook: wandb.jupyter.Notebook | None = None # type: ignore
|
130
123
|
self.printer = printer.new_printer()
|
131
124
|
|
@@ -133,6 +126,40 @@ class _WandbInit:
|
|
133
126
|
|
134
127
|
self.deprecated_features_used: dict[str, str] = dict()
|
135
128
|
|
129
|
+
@property
|
130
|
+
def _logger(self) -> wandb_setup.Logger:
|
131
|
+
return self._wl._get_logger()
|
132
|
+
|
133
|
+
def maybe_login(self, init_settings: Settings) -> None:
|
134
|
+
"""Log in if we are not creating an offline or disabled run.
|
135
|
+
|
136
|
+
This may change the W&B singleton settings.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
init_settings: Settings passed to `wandb.init()` or set via
|
140
|
+
keyword arguments.
|
141
|
+
"""
|
142
|
+
# Allow settings passed to init() to override inferred values.
|
143
|
+
#
|
144
|
+
# Calling login() may change settings on the singleton,
|
145
|
+
# so these may not be the final run settings.
|
146
|
+
run_settings = self._wl.settings.model_copy()
|
147
|
+
run_settings.update_from_settings(init_settings)
|
148
|
+
|
149
|
+
# NOTE: _noop or _offline can become true after _login().
|
150
|
+
# _noop happens if _login hits a timeout.
|
151
|
+
# _offline can be selected by the user at the login prompt.
|
152
|
+
if run_settings._noop or run_settings._offline:
|
153
|
+
return
|
154
|
+
|
155
|
+
wandb_login._login(
|
156
|
+
anonymous=run_settings.anonymous,
|
157
|
+
force=run_settings.force,
|
158
|
+
_disable_warning=True,
|
159
|
+
_silent=run_settings.quiet or run_settings.silent,
|
160
|
+
_entity=run_settings.entity,
|
161
|
+
)
|
162
|
+
|
136
163
|
def warn_env_vars_change_after_setup(self) -> None:
|
137
164
|
"""Warn if environment variables change after wandb singleton is initialized.
|
138
165
|
|
@@ -202,24 +229,15 @@ class _WandbInit:
|
|
202
229
|
warn("run_id", init_settings.run_id)
|
203
230
|
init_settings.run_id = None
|
204
231
|
|
205
|
-
def
|
206
|
-
|
207
|
-
init_settings: Settings,
|
208
|
-
config: dict | str | None = None,
|
209
|
-
config_exclude_keys: list[str] | None = None,
|
210
|
-
config_include_keys: list[str] | None = None,
|
211
|
-
allow_val_change: bool | None = None,
|
212
|
-
monitor_gym: bool | None = None,
|
213
|
-
) -> None:
|
214
|
-
"""Complete setup for `wandb.init()`.
|
232
|
+
def compute_run_settings(self, init_settings: Settings) -> Settings:
|
233
|
+
"""Returns the run's settings.
|
215
234
|
|
216
|
-
|
235
|
+
Args:
|
236
|
+
init_settings: Settings passed to `wandb.init()` or set via
|
237
|
+
keyword arguments.
|
217
238
|
"""
|
218
239
|
self.warn_env_vars_change_after_setup()
|
219
240
|
|
220
|
-
_set_logger(self._wl._get_logger())
|
221
|
-
assert logger
|
222
|
-
|
223
241
|
self.clear_run_path_if_sweep_or_launch(init_settings)
|
224
242
|
|
225
243
|
# Inherit global settings.
|
@@ -231,10 +249,121 @@ class _WandbInit:
|
|
231
249
|
# Infer the run ID from SageMaker.
|
232
250
|
if not settings.sagemaker_disable and sagemaker.is_using_sagemaker():
|
233
251
|
if sagemaker.set_run_id(settings):
|
234
|
-
|
252
|
+
self._logger.info("set run ID and group based on SageMaker")
|
235
253
|
with telemetry.context(obj=self._init_telemetry_obj) as tel:
|
236
254
|
tel.feature.sagemaker = True
|
237
255
|
|
256
|
+
# get status of code saving before applying user settings
|
257
|
+
save_code_pre_user_settings = settings.save_code
|
258
|
+
if not settings._offline and not settings._noop:
|
259
|
+
user_settings = self._wl._load_user_settings()
|
260
|
+
if user_settings is not None:
|
261
|
+
settings.update_from_dict(user_settings)
|
262
|
+
|
263
|
+
# ensure that user settings don't set saving to true
|
264
|
+
# if user explicitly set these to false in UI
|
265
|
+
if save_code_pre_user_settings is False:
|
266
|
+
settings.save_code = False
|
267
|
+
|
268
|
+
# TODO: remove this once we refactor the client. This is a temporary
|
269
|
+
# fix to make sure that we use the same project name for wandb-core.
|
270
|
+
# The reason this is not going through the settings object is to
|
271
|
+
# avoid failure cases in other parts of the code that will be
|
272
|
+
# removed with the switch to wandb-core.
|
273
|
+
if settings.project is None:
|
274
|
+
settings.project = wandb.util.auto_project_name(settings.program)
|
275
|
+
|
276
|
+
settings.x_start_time = time.time()
|
277
|
+
|
278
|
+
return settings
|
279
|
+
|
280
|
+
def _load_autoresume_run_id(self, resume_file: pathlib.Path) -> str | None:
|
281
|
+
"""Returns the run_id stored in the auto-resume file, if any.
|
282
|
+
|
283
|
+
Returns None if the file does not exist or is not in a valid format.
|
284
|
+
|
285
|
+
Args:
|
286
|
+
resume_file: The file path to use for resume='auto' mode.
|
287
|
+
"""
|
288
|
+
if not resume_file.exists():
|
289
|
+
return None
|
290
|
+
|
291
|
+
with resume_file.open() as f:
|
292
|
+
try:
|
293
|
+
return json.load(f)["run_id"]
|
294
|
+
|
295
|
+
except json.JSONDecodeError as e:
|
296
|
+
self._logger.exception(
|
297
|
+
f"could not decode {resume_file}, ignoring",
|
298
|
+
exc_info=e,
|
299
|
+
)
|
300
|
+
return None
|
301
|
+
|
302
|
+
except KeyError:
|
303
|
+
self._logger.error(
|
304
|
+
f"resume file at {resume_file} did not store a run_id"
|
305
|
+
)
|
306
|
+
return None
|
307
|
+
|
308
|
+
def _save_autoresume_run_id(
|
309
|
+
self,
|
310
|
+
*,
|
311
|
+
resume_file: pathlib.Path,
|
312
|
+
run_id: str,
|
313
|
+
) -> None:
|
314
|
+
"""Write the run ID to the auto-resume file."""
|
315
|
+
resume_file.parent.mkdir(exist_ok=True)
|
316
|
+
with resume_file.open("w") as f:
|
317
|
+
json.dump({"run_id": run_id}, f)
|
318
|
+
|
319
|
+
def set_run_id(self, settings: Settings) -> None:
|
320
|
+
"""Set the run ID and possibly save it to the auto-resume file.
|
321
|
+
|
322
|
+
After this, `settings.run_id` is guaranteed to be set.
|
323
|
+
|
324
|
+
Args:
|
325
|
+
settings: The run's settings derived from the environment
|
326
|
+
and explicit values passed to `wandb.init()`.
|
327
|
+
"""
|
328
|
+
if settings.resume == "auto" and settings.resume_fname:
|
329
|
+
resume_path = pathlib.Path(settings.resume_fname)
|
330
|
+
else:
|
331
|
+
resume_path = None
|
332
|
+
|
333
|
+
if resume_path:
|
334
|
+
previous_id = self._load_autoresume_run_id(resume_path)
|
335
|
+
|
336
|
+
if not previous_id:
|
337
|
+
pass
|
338
|
+
elif settings.run_id is None:
|
339
|
+
self._logger.info(f"loaded run ID from {resume_path}")
|
340
|
+
settings.run_id = previous_id
|
341
|
+
elif settings.run_id != previous_id:
|
342
|
+
wandb.termwarn(
|
343
|
+
f"Ignoring ID {previous_id} loaded due to resume='auto'"
|
344
|
+
f" because the run ID is set to {settings.run_id}.",
|
345
|
+
)
|
346
|
+
|
347
|
+
# If no run ID was inferred, explicitly set, or loaded from an
|
348
|
+
# auto-resume file, then we generate a new ID.
|
349
|
+
if settings.run_id is None:
|
350
|
+
settings.run_id = runid.generate_id()
|
351
|
+
|
352
|
+
if resume_path:
|
353
|
+
self._save_autoresume_run_id(
|
354
|
+
resume_file=resume_path,
|
355
|
+
run_id=settings.run_id,
|
356
|
+
)
|
357
|
+
|
358
|
+
def setup(
|
359
|
+
self,
|
360
|
+
settings: Settings,
|
361
|
+
config: dict | str | None = None,
|
362
|
+
config_exclude_keys: list[str] | None = None,
|
363
|
+
config_include_keys: list[str] | None = None,
|
364
|
+
monitor_gym: bool | None = None,
|
365
|
+
) -> None:
|
366
|
+
"""Compute the run's config and some telemetry."""
|
238
367
|
with telemetry.context(obj=self._init_telemetry_obj) as tel:
|
239
368
|
if config is not None:
|
240
369
|
tel.feature.set_init_config = True
|
@@ -295,55 +424,6 @@ class _WandbInit:
|
|
295
424
|
with telemetry.context(obj=self._init_telemetry_obj) as tel:
|
296
425
|
tel.feature.tensorboard_sync = True
|
297
426
|
|
298
|
-
if not settings._offline and not settings._noop:
|
299
|
-
wandb_login._login(
|
300
|
-
anonymous=settings.anonymous,
|
301
|
-
force=settings.force,
|
302
|
-
_disable_warning=True,
|
303
|
-
_silent=settings.quiet or settings.silent,
|
304
|
-
_entity=settings.entity,
|
305
|
-
)
|
306
|
-
|
307
|
-
# apply updated global state after login was handled
|
308
|
-
login_settings = {
|
309
|
-
k: v
|
310
|
-
for k, v in {
|
311
|
-
"anonymous": self._wl.settings.anonymous,
|
312
|
-
"api_key": self._wl.settings.api_key,
|
313
|
-
"base_url": self._wl.settings.base_url,
|
314
|
-
"force": self._wl.settings.force,
|
315
|
-
"login_timeout": self._wl.settings.login_timeout,
|
316
|
-
}.items()
|
317
|
-
if v is not None
|
318
|
-
}
|
319
|
-
if login_settings:
|
320
|
-
settings.update_from_dict(login_settings)
|
321
|
-
|
322
|
-
# handle custom resume logic
|
323
|
-
settings.handle_resume_logic()
|
324
|
-
|
325
|
-
# get status of code saving before applying user settings
|
326
|
-
save_code_pre_user_settings = settings.save_code
|
327
|
-
if not settings._offline and not settings._noop:
|
328
|
-
user_settings = self._wl._load_user_settings()
|
329
|
-
if user_settings is not None:
|
330
|
-
settings.update_from_dict(user_settings)
|
331
|
-
|
332
|
-
# ensure that user settings don't set saving to true
|
333
|
-
# if user explicitly set these to false in UI
|
334
|
-
if save_code_pre_user_settings is False:
|
335
|
-
settings.save_code = False
|
336
|
-
|
337
|
-
# TODO: remove this once we refactor the client. This is a temporary
|
338
|
-
# fix to make sure that we use the same project name for wandb-core.
|
339
|
-
# The reason this is not going through the settings object is to
|
340
|
-
# avoid failure cases in other parts of the code that will be
|
341
|
-
# removed with the switch to wandb-core.
|
342
|
-
if settings.project is None:
|
343
|
-
settings.project = wandb.util.auto_project_name(settings.program)
|
344
|
-
|
345
|
-
settings.x_start_time = time.time()
|
346
|
-
|
347
427
|
if not settings._noop:
|
348
428
|
self._log_setup(settings)
|
349
429
|
|
@@ -353,13 +433,10 @@ class _WandbInit:
|
|
353
433
|
if launch_config:
|
354
434
|
self._split_artifacts_from_config(launch_config, self.launch_config)
|
355
435
|
|
356
|
-
self.settings = settings
|
357
|
-
|
358
436
|
def teardown(self) -> None:
|
359
437
|
# TODO: currently this is only called on failed wandb.init attempts
|
360
438
|
# normally this happens on the run object
|
361
|
-
|
362
|
-
logger.info("tearing down wandb.init")
|
439
|
+
self._logger.info("tearing down wandb.init")
|
363
440
|
for hook in self._teardown_hooks:
|
364
441
|
hook.call()
|
365
442
|
|
@@ -372,11 +449,12 @@ class _WandbInit:
|
|
372
449
|
else:
|
373
450
|
config_target.setdefault(k, v)
|
374
451
|
|
375
|
-
def
|
376
|
-
"""
|
452
|
+
def _create_logger(self, log_fname: str) -> logging.Logger:
|
453
|
+
"""Returns a logger configured to write to a file.
|
377
454
|
|
378
|
-
This adds a run_id to the log, in case of multiple processes on the same
|
379
|
-
Currently, there is no way to disable logging after it's
|
455
|
+
This adds a run_id to the log, in case of multiple processes on the same
|
456
|
+
machine. Currently, there is no way to disable logging after it's
|
457
|
+
enabled.
|
380
458
|
"""
|
381
459
|
handler = logging.FileHandler(log_fname)
|
382
460
|
handler.setLevel(logging.INFO)
|
@@ -387,7 +465,8 @@ class _WandbInit:
|
|
387
465
|
)
|
388
466
|
|
389
467
|
handler.setFormatter(formatter)
|
390
|
-
|
468
|
+
|
469
|
+
logger = logging.getLogger("wandb")
|
391
470
|
logger.propagate = False
|
392
471
|
logger.addHandler(handler)
|
393
472
|
# TODO: make me configurable
|
@@ -399,6 +478,8 @@ class _WandbInit:
|
|
399
478
|
)
|
400
479
|
)
|
401
480
|
|
481
|
+
return logger
|
482
|
+
|
402
483
|
def _safe_symlink(
|
403
484
|
self, base: str, target: str, name: str, delete: bool = False
|
404
485
|
) -> None:
|
@@ -429,14 +510,14 @@ class _WandbInit:
|
|
429
510
|
if self.notebook.save_ipynb(): # type: ignore
|
430
511
|
assert self.run is not None
|
431
512
|
res = self.run.log_code(root=None)
|
432
|
-
|
513
|
+
self._logger.info("saved code: %s", res) # type: ignore
|
433
514
|
if self.backend.interface is not None:
|
434
|
-
|
515
|
+
self._logger.info("pausing backend") # type: ignore
|
435
516
|
self.backend.interface.publish_pause()
|
436
517
|
|
437
518
|
def _resume_backend(self, *args: Any, **kwargs: Any) -> None: # noqa
|
438
519
|
if self.backend is not None and self.backend.interface is not None:
|
439
|
-
|
520
|
+
self._logger.info("resuming backend") # type: ignore
|
440
521
|
self.backend.interface.publish_resume()
|
441
522
|
|
442
523
|
def _jupyter_teardown(self) -> None:
|
@@ -447,8 +528,8 @@ class _WandbInit:
|
|
447
528
|
if self.notebook.save_ipynb():
|
448
529
|
assert self.run is not None
|
449
530
|
res = self.run.log_code(root=None)
|
450
|
-
|
451
|
-
|
531
|
+
self._logger.info("saved code and history: %s", res) # type: ignore
|
532
|
+
self._logger.info("cleaning up jupyter logic") # type: ignore
|
452
533
|
# because of how we bind our methods we manually find them to unregister
|
453
534
|
for hook in ipython.events.callbacks["pre_run_cell"]:
|
454
535
|
if "_resume_backend" in hook.__name__:
|
@@ -466,7 +547,7 @@ class _WandbInit:
|
|
466
547
|
|
467
548
|
# Monkey patch ipython publish to capture displayed outputs
|
468
549
|
if not hasattr(ipython.display_pub, "_orig_publish"):
|
469
|
-
|
550
|
+
self._logger.info("configuring jupyter hooks %s", self) # type: ignore
|
470
551
|
ipython.display_pub._orig_publish = ipython.display_pub.publish
|
471
552
|
# Registering resume and pause hooks
|
472
553
|
|
@@ -513,15 +594,9 @@ class _WandbInit:
|
|
513
594
|
delete=True,
|
514
595
|
)
|
515
596
|
|
516
|
-
|
517
|
-
self.
|
518
|
-
|
519
|
-
assert self._wl
|
520
|
-
assert logger
|
521
|
-
|
522
|
-
self._wl._early_logger_flush(logger)
|
523
|
-
logger.info(f"Logging user logs to {settings.log_user}")
|
524
|
-
logger.info(f"Logging internal logs to {settings.log_internal}")
|
597
|
+
self._wl._early_logger_flush(self._create_logger(settings.log_user))
|
598
|
+
self._logger.info(f"Logging user logs to {settings.log_user}")
|
599
|
+
self._logger.info(f"Logging internal logs to {settings.log_internal}")
|
525
600
|
|
526
601
|
def _make_run_disabled(self) -> Run:
|
527
602
|
"""Returns a Run-like object where all methods are no-ops.
|
@@ -635,24 +710,20 @@ class _WandbInit:
|
|
635
710
|
percent_done = handle.percent_done
|
636
711
|
self.printer.progress_update(line, percent_done=percent_done)
|
637
712
|
|
638
|
-
def init(self) -> Run: # noqa: C901
|
639
|
-
|
640
|
-
raise RuntimeError("Logger not initialized")
|
641
|
-
logger.info("calling init triggers")
|
713
|
+
def init(self, settings: Settings) -> Run: # noqa: C901
|
714
|
+
self._logger.info("calling init triggers")
|
642
715
|
trigger.call("on_init")
|
643
716
|
|
644
|
-
assert self.settings is not None
|
645
717
|
assert self._wl is not None
|
646
718
|
|
647
|
-
|
719
|
+
self._logger.info(
|
648
720
|
f"wandb.init called with sweep_config: {self.sweep_config}\nconfig: {self.config}"
|
649
721
|
)
|
650
722
|
|
651
|
-
if
|
723
|
+
if settings._noop:
|
652
724
|
return self._make_run_disabled()
|
653
725
|
if (
|
654
|
-
|
655
|
-
or (self.settings._jupyter and self.settings.reinit is not False)
|
726
|
+
settings.reinit or (settings._jupyter and settings.reinit is not False)
|
656
727
|
) and len(self._wl._global_run_stack) > 0:
|
657
728
|
if len(self._wl._global_run_stack) > 1:
|
658
729
|
wandb.termwarn(
|
@@ -663,39 +734,39 @@ class _WandbInit:
|
|
663
734
|
)
|
664
735
|
|
665
736
|
latest_run = self._wl._global_run_stack[-1]
|
666
|
-
|
737
|
+
self._logger.info(f"found existing run on stack: {latest_run.id}")
|
667
738
|
latest_run.finish()
|
668
739
|
elif wandb.run is not None and os.getpid() == wandb.run._init_pid:
|
669
|
-
|
740
|
+
self._logger.info("wandb.init() called when a run is still active")
|
670
741
|
with telemetry.context() as tel:
|
671
742
|
tel.feature.init_return_run = True
|
672
743
|
return wandb.run
|
673
744
|
|
674
|
-
|
745
|
+
self._logger.info("starting backend")
|
675
746
|
|
676
|
-
if not
|
747
|
+
if not settings.x_disable_service:
|
677
748
|
service = self._wl.ensure_service()
|
678
|
-
|
749
|
+
self._logger.info("sending inform_init request")
|
679
750
|
service.inform_init(
|
680
|
-
settings=
|
681
|
-
run_id=
|
751
|
+
settings=settings.to_proto(),
|
752
|
+
run_id=settings.run_id, # type: ignore
|
682
753
|
)
|
683
754
|
else:
|
684
755
|
service = None
|
685
756
|
|
686
757
|
mailbox = Mailbox()
|
687
758
|
backend = Backend(
|
688
|
-
settings=
|
759
|
+
settings=settings,
|
689
760
|
service=service,
|
690
761
|
mailbox=mailbox,
|
691
762
|
)
|
692
763
|
backend.ensure_launched()
|
693
|
-
|
764
|
+
self._logger.info("backend started and connected")
|
694
765
|
|
695
766
|
# resuming needs access to the server, check server_status()?
|
696
767
|
run = Run(
|
697
768
|
config=self.config,
|
698
|
-
settings=
|
769
|
+
settings=settings,
|
699
770
|
sweep_config=self.sweep_config,
|
700
771
|
launch_config=self.launch_config,
|
701
772
|
)
|
@@ -708,18 +779,18 @@ class _WandbInit:
|
|
708
779
|
hf_version = _huggingface_version()
|
709
780
|
if hf_version:
|
710
781
|
tel.huggingface_version = hf_version
|
711
|
-
if
|
782
|
+
if settings._jupyter:
|
712
783
|
tel.env.jupyter = True
|
713
|
-
if
|
784
|
+
if settings._ipython:
|
714
785
|
tel.env.ipython = True
|
715
|
-
if
|
786
|
+
if settings._colab:
|
716
787
|
tel.env.colab = True
|
717
|
-
if
|
788
|
+
if settings._kaggle:
|
718
789
|
tel.env.kaggle = True
|
719
|
-
if
|
790
|
+
if settings._windows:
|
720
791
|
tel.env.windows = True
|
721
792
|
|
722
|
-
if
|
793
|
+
if settings.launch:
|
723
794
|
tel.feature.launch = True
|
724
795
|
|
725
796
|
for module_name in telemetry.list_telemetry_imports(only_imported=True):
|
@@ -727,8 +798,8 @@ class _WandbInit:
|
|
727
798
|
|
728
799
|
# probe the active start method
|
729
800
|
active_start_method: str | None = None
|
730
|
-
if
|
731
|
-
active_start_method =
|
801
|
+
if settings.start_method == "thread":
|
802
|
+
active_start_method = settings.start_method
|
732
803
|
else:
|
733
804
|
active_start_method = getattr(
|
734
805
|
backend._multiprocessing, "get_start_method", lambda: None
|
@@ -746,7 +817,7 @@ class _WandbInit:
|
|
746
817
|
if os.environ.get("PEX"):
|
747
818
|
tel.env.pex = True
|
748
819
|
|
749
|
-
if
|
820
|
+
if settings._aws_lambda:
|
750
821
|
tel.env.aws_lambda = True
|
751
822
|
|
752
823
|
if os.environ.get(wandb.env._DISABLE_SERVICE):
|
@@ -754,13 +825,13 @@ class _WandbInit:
|
|
754
825
|
|
755
826
|
if service:
|
756
827
|
tel.feature.service = True
|
757
|
-
if
|
828
|
+
if settings.x_flow_control_disabled:
|
758
829
|
tel.feature.flow_control_disabled = True
|
759
|
-
if
|
830
|
+
if settings.x_flow_control_custom:
|
760
831
|
tel.feature.flow_control_custom = True
|
761
|
-
if not
|
832
|
+
if not settings.x_require_legacy_service:
|
762
833
|
tel.feature.core = True
|
763
|
-
if
|
834
|
+
if settings._shared:
|
764
835
|
wandb.termwarn(
|
765
836
|
"The `_shared` feature is experimental and may change. "
|
766
837
|
"Please contact support@wandb.com for guidance and to report any issues."
|
@@ -769,7 +840,7 @@ class _WandbInit:
|
|
769
840
|
|
770
841
|
tel.env.maybe_mp = _maybe_mp_process(backend)
|
771
842
|
|
772
|
-
if not
|
843
|
+
if not settings.label_disable:
|
773
844
|
if self.notebook:
|
774
845
|
run._label_probe_notebook(self.notebook)
|
775
846
|
else:
|
@@ -783,7 +854,7 @@ class _WandbInit:
|
|
783
854
|
run=run,
|
784
855
|
)
|
785
856
|
|
786
|
-
|
857
|
+
self._logger.info("updated telemetry")
|
787
858
|
|
788
859
|
run._set_library(self._wl)
|
789
860
|
run._set_backend(backend)
|
@@ -797,25 +868,27 @@ class _WandbInit:
|
|
797
868
|
# Using GitRepo() blocks & can be slow, depending on user's current git setup.
|
798
869
|
# We don't want to block run initialization/start request, so populate run's git
|
799
870
|
# info beforehand.
|
800
|
-
if not (
|
871
|
+
if not (settings.disable_git or settings.x_disable_machine_info):
|
801
872
|
run._populate_git_info()
|
802
873
|
|
803
874
|
run_result: pb.RunUpdateResult | None = None
|
804
875
|
|
805
|
-
if
|
876
|
+
if settings._offline:
|
806
877
|
with telemetry.context(run=run) as tel:
|
807
878
|
tel.feature.offline = True
|
808
879
|
|
809
|
-
if
|
880
|
+
if settings.resume:
|
810
881
|
wandb.termwarn(
|
811
882
|
"`resume` will be ignored since W&B syncing is set to `offline`. "
|
812
883
|
f"Starting a new run with run id {run.id}."
|
813
884
|
)
|
814
885
|
error: wandb.Error | None = None
|
815
886
|
|
816
|
-
timeout =
|
887
|
+
timeout = settings.init_timeout
|
817
888
|
|
818
|
-
|
889
|
+
self._logger.info(
|
890
|
+
f"communicating run to backend with {timeout} second timeout",
|
891
|
+
)
|
819
892
|
|
820
893
|
run_init_handle = backend.interface.deliver_run(run)
|
821
894
|
result = run_init_handle.wait(
|
@@ -842,7 +915,7 @@ class _WandbInit:
|
|
842
915
|
error = ProtobufErrorHandler.to_exception(run_result.error)
|
843
916
|
|
844
917
|
if error is not None:
|
845
|
-
|
918
|
+
self._logger.error(f"encountered error: {error}")
|
846
919
|
if not service:
|
847
920
|
# Shutdown the backend and get rid of the logger
|
848
921
|
# we don't need to do console cleanup at this point
|
@@ -860,19 +933,19 @@ class _WandbInit:
|
|
860
933
|
)
|
861
934
|
|
862
935
|
if run_result.run.resumed:
|
863
|
-
|
936
|
+
self._logger.info("run resumed")
|
864
937
|
with telemetry.context(run=run) as tel:
|
865
938
|
tel.feature.resumed = run_result.run.resumed
|
866
939
|
run._set_run_obj(run_result.run)
|
867
940
|
|
868
|
-
|
941
|
+
self._logger.info("starting run threads in backend")
|
869
942
|
# initiate run (stats and metadata probing)
|
870
943
|
|
871
944
|
if service:
|
872
|
-
assert
|
945
|
+
assert settings.run_id
|
873
946
|
service.inform_start(
|
874
|
-
settings=
|
875
|
-
run_id=
|
947
|
+
settings=settings.to_proto(),
|
948
|
+
run_id=settings.run_id,
|
876
949
|
)
|
877
950
|
|
878
951
|
assert backend.interface
|
@@ -889,11 +962,11 @@ class _WandbInit:
|
|
889
962
|
|
890
963
|
run._handle_launch_artifact_overrides()
|
891
964
|
if (
|
892
|
-
|
893
|
-
and
|
894
|
-
and os.path.exists(
|
965
|
+
settings.launch
|
966
|
+
and settings.launch_config_path
|
967
|
+
and os.path.exists(settings.launch_config_path)
|
895
968
|
):
|
896
|
-
run.save(
|
969
|
+
run.save(settings.launch_config_path)
|
897
970
|
# put artifacts in run config here
|
898
971
|
# since doing so earlier will cause an error
|
899
972
|
# as the run is not upserted
|
@@ -907,7 +980,7 @@ class _WandbInit:
|
|
907
980
|
|
908
981
|
self.backend = backend
|
909
982
|
run._on_start()
|
910
|
-
|
983
|
+
self._logger.info("run started, returning control to user process")
|
911
984
|
return run
|
912
985
|
|
913
986
|
|
@@ -938,10 +1011,7 @@ def _attach(
|
|
938
1011
|
wandb._assert_is_user_process() # type: ignore
|
939
1012
|
|
940
1013
|
_wl = wandb.setup()
|
941
|
-
|
942
|
-
_set_logger(_wl._get_logger())
|
943
|
-
if logger is None:
|
944
|
-
raise UsageError("logger is not initialized")
|
1014
|
+
logger = _wl._get_logger()
|
945
1015
|
|
946
1016
|
service = _wl.ensure_service()
|
947
1017
|
|
@@ -1276,27 +1346,36 @@ def init( # noqa: C901
|
|
1276
1346
|
if resume_from is not None:
|
1277
1347
|
init_settings.resume_from = resume_from # type: ignore
|
1278
1348
|
|
1349
|
+
wl: wandb_setup._WandbSetup | None = None
|
1350
|
+
|
1279
1351
|
try:
|
1280
|
-
|
1352
|
+
wl = wandb.setup()
|
1353
|
+
|
1354
|
+
wi = _WandbInit(wl)
|
1355
|
+
|
1356
|
+
wi.maybe_login(init_settings)
|
1357
|
+
run_settings = wi.compute_run_settings(init_settings)
|
1358
|
+
wi.set_run_id(run_settings)
|
1359
|
+
|
1281
1360
|
wi.setup(
|
1282
|
-
|
1361
|
+
settings=run_settings,
|
1283
1362
|
config=config,
|
1284
1363
|
config_exclude_keys=config_exclude_keys,
|
1285
1364
|
config_include_keys=config_include_keys,
|
1286
|
-
allow_val_change=allow_val_change,
|
1287
1365
|
monitor_gym=monitor_gym,
|
1288
1366
|
)
|
1289
|
-
|
1367
|
+
|
1368
|
+
return wi.init(run_settings)
|
1290
1369
|
|
1291
1370
|
except KeyboardInterrupt as e:
|
1292
|
-
if
|
1293
|
-
|
1371
|
+
if wl:
|
1372
|
+
wl._get_logger().warning("interrupted", exc_info=e)
|
1294
1373
|
|
1295
1374
|
raise
|
1296
1375
|
|
1297
1376
|
except Exception as e:
|
1298
|
-
if
|
1299
|
-
|
1377
|
+
if wl:
|
1378
|
+
wl._get_logger().exception("error in wandb.init()", exc_info=e)
|
1300
1379
|
|
1301
1380
|
# Need to build delay into this sentry capture because our exit hooks
|
1302
1381
|
# mess with sentry's ability to send out errors before the program ends.
|
wandb/sdk/wandb_run.py
CHANGED
@@ -29,7 +29,6 @@ import wandb.util
|
|
29
29
|
from wandb import trigger
|
30
30
|
from wandb._globals import _datatypes_set_callback
|
31
31
|
from wandb.apis import internal, public
|
32
|
-
from wandb.apis.internal import Api
|
33
32
|
from wandb.apis.public import Api as PublicApi
|
34
33
|
from wandb.errors import CommError, UnsupportedError, UsageError
|
35
34
|
from wandb.errors.links import url_registry
|
@@ -1814,7 +1813,10 @@ class Run:
|
|
1814
1813
|
examples = []
|
1815
1814
|
for i in range(3):
|
1816
1815
|
pixels = np.random.randint(
|
1817
|
-
low=0,
|
1816
|
+
low=0,
|
1817
|
+
high=256,
|
1818
|
+
size=(100, 100, 3),
|
1819
|
+
dtype=np.uint8,
|
1818
1820
|
)
|
1819
1821
|
pil_image = PILImage.fromarray(pixels, mode="RGB")
|
1820
1822
|
image = wandb.Image(pil_image, caption=f"random field {i}")
|
@@ -1831,7 +1833,10 @@ class Run:
|
|
1831
1833
|
run = wandb.init()
|
1832
1834
|
# axes are (time, channel, height, width)
|
1833
1835
|
frames = np.random.randint(
|
1834
|
-
low=0,
|
1836
|
+
low=0,
|
1837
|
+
high=256,
|
1838
|
+
size=(10, 3, 100, 100),
|
1839
|
+
dtype=np.uint8,
|
1835
1840
|
)
|
1836
1841
|
run.log({"video": wandb.Video(frames, fps=4)})
|
1837
1842
|
```
|
@@ -3266,8 +3271,7 @@ class Run:
|
|
3266
3271
|
is_user_created: bool = False,
|
3267
3272
|
use_after_commit: bool = False,
|
3268
3273
|
) -> Artifact:
|
3269
|
-
|
3270
|
-
if api.settings().get("anonymous") in ["allow", "must"]:
|
3274
|
+
if self._settings.anonymous in ["allow", "must"]:
|
3271
3275
|
wandb.termwarn(
|
3272
3276
|
"Artifacts logged anonymously cannot be claimed and expire after 7 days."
|
3273
3277
|
)
|
@@ -3864,8 +3868,7 @@ class Run:
|
|
3864
3868
|
f'{printer.emoji("rocket")} View run at {printer.link(run_url)}',
|
3865
3869
|
)
|
3866
3870
|
|
3867
|
-
|
3868
|
-
if run_name and Api().api.settings().get("anonymous") in ["allow", "must"]:
|
3871
|
+
if run_name and settings.anonymous in ["allow", "must"]:
|
3869
3872
|
printer.display(
|
3870
3873
|
(
|
3871
3874
|
"Do NOT share these links with anyone."
|
wandb/sdk/wandb_settings.py
CHANGED
@@ -34,14 +34,12 @@ from pydantic_core import SchemaValidator, core_schema
|
|
34
34
|
|
35
35
|
import wandb
|
36
36
|
from wandb import env, termwarn, util
|
37
|
-
from wandb.apis.internal import Api
|
38
37
|
from wandb.errors import UsageError
|
39
38
|
from wandb.proto import wandb_settings_pb2
|
40
39
|
|
41
|
-
from .lib import apikey, credentials,
|
40
|
+
from .lib import apikey, credentials, ipython
|
42
41
|
from .lib.gitlib import GitRepo
|
43
42
|
from .lib.run_moment import RunMoment
|
44
|
-
from .lib.runid import generate_id
|
45
43
|
|
46
44
|
|
47
45
|
def _path_convert(*args: str) -> str:
|
@@ -1154,29 +1152,6 @@ class Settings(BaseModel, validate_assignment=True):
|
|
1154
1152
|
|
1155
1153
|
return settings_proto
|
1156
1154
|
|
1157
|
-
def handle_resume_logic(self):
|
1158
|
-
"""Handle logic for resuming runs."""
|
1159
|
-
# handle auto resume logic
|
1160
|
-
if self.resume == "auto":
|
1161
|
-
if os.path.exists(self.resume_fname):
|
1162
|
-
with open(self.resume_fname) as f:
|
1163
|
-
resume_run_id = json.load(f)["run_id"]
|
1164
|
-
if self.run_id is None:
|
1165
|
-
self.run_id = resume_run_id
|
1166
|
-
elif self.run_id != resume_run_id:
|
1167
|
-
wandb.termwarn(
|
1168
|
-
"Tried to auto resume run with "
|
1169
|
-
f"id {resume_run_id} but id {self.run_id} is set.",
|
1170
|
-
)
|
1171
|
-
if self.run_id is None:
|
1172
|
-
self.run_id = generate_id()
|
1173
|
-
|
1174
|
-
# persist run_id in case of failure
|
1175
|
-
if self.resume == "auto" and self.resume_fname is not None:
|
1176
|
-
filesystem.mkdir_exists_ok(self.wandb_dir)
|
1177
|
-
with open(self.resume_fname, "w") as f:
|
1178
|
-
f.write(json.dumps({"run_id": self.run_id}))
|
1179
|
-
|
1180
1155
|
@staticmethod
|
1181
1156
|
def validate_url(url: str) -> None:
|
1182
1157
|
"""Validate a URL string."""
|
@@ -1262,7 +1237,7 @@ class Settings(BaseModel, validate_assignment=True):
|
|
1262
1237
|
def _get_url_query_string(self) -> str:
|
1263
1238
|
"""Construct the query string for project, run, and sweep URLs."""
|
1264
1239
|
# TODO: remove dependency on Api()
|
1265
|
-
if
|
1240
|
+
if self.anonymous not in ["allow", "must"]:
|
1266
1241
|
return ""
|
1267
1242
|
|
1268
1243
|
api_key = apikey.api_key(settings=self)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
package_readme.md,sha256=U9047nyMDICgctm1HLm4HfXwFnFKsEn2m77hsYPUZ1I,4298
|
2
|
-
wandb/__init__.py,sha256=
|
3
|
-
wandb/__init__.pyi,sha256=
|
2
|
+
wandb/__init__.py,sha256=5f1_Sih9Sxjo5YN6UOofmcFjW0XnL5FxgWk-saYyMhw,6988
|
3
|
+
wandb/__init__.pyi,sha256=__KjZYDXGiHshy_OUrsV7chJrIiOon8DuzRjM6ubHnc,47024
|
4
4
|
wandb/__main__.py,sha256=gripuDgB7J8wMMeJt4CIBRjn1BMSFr5zvsrt585Pnj4,64
|
5
5
|
wandb/_globals.py,sha256=CccwOAls5bxJArYHg12b08ZeKR8Qu9u57GtYWjBH0o0,702
|
6
6
|
wandb/data_types.py,sha256=tjxcQ8padGuGxST192PyEDX_nhU__izHcAK-kaSyevI,2276
|
@@ -104,7 +104,7 @@ wandb/integration/lightning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
104
104
|
wandb/integration/lightning/fabric/__init__.py,sha256=RFhr2VkC0D8b6bAXUMZzcVzqDQaoOozfP_HOogAWi9o,94
|
105
105
|
wandb/integration/lightning/fabric/logger.py,sha256=ev8xFbCohaRp4MvrBn1x_5ypuvLe2FJdUWY7Jjw0ylk,27251
|
106
106
|
wandb/integration/metaflow/__init__.py,sha256=nYn3ubiX9Ay6PFxr7r7F8Ia_2dLImb63rpYDmuDlkkQ,109
|
107
|
-
wandb/integration/metaflow/metaflow.py,sha256=
|
107
|
+
wandb/integration/metaflow/metaflow.py,sha256=qlzrdkTmT_KTg6sUE3PV8PStuZyFGYEdQzNNNil05jI,11804
|
108
108
|
wandb/integration/openai/__init__.py,sha256=T6x9lIFfw2NzOSi46wi3otY_-DSwyMgnIjMIOIod7iU,66
|
109
109
|
wandb/integration/openai/fine_tuning.py,sha256=w9_F3bLTG72KdNkD2rAPRdrq6rc58EtltFxwedyI690,18555
|
110
110
|
wandb/integration/openai/openai.py,sha256=zGD1kj6yjDP1IfAAYRcltuXD5Bf569CSnMHMf4rDm54,496
|
@@ -203,14 +203,14 @@ wandb/sdk/__init__.py,sha256=N-GTAC0AzbZF2J8RzB33DTmYk9u-jubllCwvhWrPgsE,813
|
|
203
203
|
wandb/sdk/wandb_alerts.py,sha256=SwBPBiXRxknMTMGbsVoMMWqWK65UWMcKAdTWZtdwAeo,193
|
204
204
|
wandb/sdk/wandb_config.py,sha256=b7kxQVnIh5HCBZXb2pOGZ4c02xCVlW4IQiAu3N-8Opg,10856
|
205
205
|
wandb/sdk/wandb_helper.py,sha256=IbJ7opO8UkfwCDekSjRYIrGBblUxnTPBfp1EdesfF4U,1824
|
206
|
-
wandb/sdk/wandb_init.py,sha256=
|
206
|
+
wandb/sdk/wandb_init.py,sha256=z19KqQWjmOcnswowWoq4VAHGalTmjLKwz1R-Rm1i-Bo,56484
|
207
207
|
wandb/sdk/wandb_login.py,sha256=DP7nDUGx2UmqGRBrvTmcpvzRBVeRD0qEENtmu4sjDAQ,10966
|
208
208
|
wandb/sdk/wandb_metadata.py,sha256=nT6TUF4Yh-ka3VQGyKd3y9MTEHJUgRVT4ICyfJkbHFo,20111
|
209
209
|
wandb/sdk/wandb_metric.py,sha256=a3GiQXr6H18m81uobYjlJaC8CL8iANzI42qxkxfZsDs,3268
|
210
210
|
wandb/sdk/wandb_require.py,sha256=Y0ib8h27__t7hXos1F2srfsQzVfzH4BB6wq8E1aRbRA,2950
|
211
211
|
wandb/sdk/wandb_require_helpers.py,sha256=ZmKv5aXXHDTTU6nYHMLKW4_pt9X-PlaMtbRJl77kHX8,1331
|
212
|
-
wandb/sdk/wandb_run.py,sha256=
|
213
|
-
wandb/sdk/wandb_settings.py,sha256=
|
212
|
+
wandb/sdk/wandb_run.py,sha256=eI6WIi2pmkBkP5aMgscMU9C94PjGVknEYQvVPlC-YDM,155668
|
213
|
+
wandb/sdk/wandb_settings.py,sha256=gXZydMDYH8OLcAoK78mA4naRqBA2aKlsIGKn3i4OC0s,47290
|
214
214
|
wandb/sdk/wandb_setup.py,sha256=7j3UBiqm8x7f4JsFPX5jR19wNRSRvf77TIyncd0HpJg,13014
|
215
215
|
wandb/sdk/wandb_summary.py,sha256=yQdOVIPrZaZanhBQ7yuSfPLX0x6dxwkN_KAn4SgjSZU,4536
|
216
216
|
wandb/sdk/wandb_sweep.py,sha256=Sg_JqxVzmjUBvii41azpdr-c6RPwHOBnSha8k7jrRhk,4028
|
@@ -816,8 +816,8 @@ wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/importlib2.py,sha256=cJIaJ2EQso
|
|
816
816
|
wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/platform.py,sha256=UORYTNVcUSE2NpFcq9UVLIS-tsS0TS_Qw8akhKxn2eY,1506
|
817
817
|
wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/unicode_paths.py,sha256=UWX8DB97ygkEeSxWQUYCHR4MahNilux7vl5TCTQtPPk,2190
|
818
818
|
wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/win32stat.py,sha256=ZOevOTbSo8NRiIxkuBVGaG4yigWnPoO0goxAi-jsBkM,3828
|
819
|
-
wandb-0.19.
|
820
|
-
wandb-0.19.
|
821
|
-
wandb-0.19.
|
822
|
-
wandb-0.19.
|
823
|
-
wandb-0.19.
|
819
|
+
wandb-0.19.3.dist-info/METADATA,sha256=AGD2Iwy-cUjmtannnNpN4Nh9wQAjRZw7WgFow2-DvwI,10282
|
820
|
+
wandb-0.19.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
821
|
+
wandb-0.19.3.dist-info/entry_points.txt,sha256=v4FCOZ9gW7Pc6KLsmgQqpCiKTrA1wh2XHmNf-NUP1-I,67
|
822
|
+
wandb-0.19.3.dist-info/licenses/LICENSE,sha256=izOKRJpGOx1PrJiGOKR0HsNdlB5JdH2d0Z4P7a7ssTc,1081
|
823
|
+
wandb-0.19.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|