Skip to content

Add Player.log to results folder #3877

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.ml-agents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ and this project adheres to
added in `CollectObservations()`. (#3825)
- Model updates can now happen asynchronously with environment steps for better performance. (#3690)
- `num_updates` and `train_interval` for SAC were replaced with `steps_per_update`. (#3690)
- Unity Player logs are now written out to the results directory. (#3877)

### Bug Fixes

Expand Down
30 changes: 22 additions & 8 deletions ml-agents-envs/mlagents_envs/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ def __init__(
seed: int = 0,
no_graphics: bool = False,
timeout_wait: int = 60,
args: Optional[List[str]] = None,
additional_args: Optional[List[str]] = None,
side_channels: Optional[List[SideChannel]] = None,
log_folder: Optional[str] = None,
):
"""
Starts a new unity environment and establishes a connection with the environment.
Expand All @@ -136,9 +137,11 @@ def __init__(
:int timeout_wait: Time (in seconds) to wait for connection from environment.
:list args: Addition Unity command line arguments
:list side_channels: Additional side channel for no-rl communication with Unity
:str log_folder: Optional folder to write the Unity Player log file into. Requires absolute path.
"""
args = args or []
atexit.register(self._close)
self.additional_args = additional_args or []
self.no_graphics = no_graphics
# If base port is not specified, use BASE_ENVIRONMENT_PORT if we have
# an environment, otherwise DEFAULT_EDITOR_PORT
if base_port is None:
Expand All @@ -164,6 +167,7 @@ def __init__(
)
)
self.side_channels[_sc.channel_id] = _sc
self.log_folder = log_folder

# If the environment name is None, a new environment will not be launched
# and the communicator will directly try to connect to an existing unity environment.
Expand All @@ -174,7 +178,7 @@ def __init__(
"the worker-id must be 0 in order to connect with the Editor."
)
if file_name is not None:
self.executable_launcher(file_name, no_graphics, args)
self.executable_launcher(file_name, no_graphics, additional_args)
else:
logger.info(
f"Listening on port {self.port}. "
Expand Down Expand Up @@ -268,6 +272,20 @@ def validate_environment_path(env_path: str) -> Optional[str]:
launch_string = candidates[0]
return launch_string

def executable_args(self) -> List[str]:
args: List[str] = []
if self.no_graphics:
args += ["-nographics", "-batchmode"]
args += [UnityEnvironment.PORT_COMMAND_LINE_ARG, str(self.port)]
if self.log_folder:
log_file_path = os.path.join(
self.log_folder, f"Player-{self.worker_id}.log"
)
args += ["-logFile", log_file_path]
# Add in arguments passed explicitly by the user.
args += self.additional_args
return args

def executable_launcher(self, file_name, no_graphics, args):
launch_string = self.validate_environment_path(file_name)
if launch_string is None:
Expand All @@ -278,11 +296,7 @@ def executable_launcher(self, file_name, no_graphics, args):
else:
logger.debug("This is the launch string {}".format(launch_string))
# Launch Unity environment
subprocess_args = [launch_string]
if no_graphics:
subprocess_args += ["-nographics", "-batchmode"]
subprocess_args += [UnityEnvironment.PORT_COMMAND_LINE_ARG, str(self.port)]
subprocess_args += args
subprocess_args = [launch_string] + self.executable_args()
try:
self.proc1 = subprocess.Popen(
subprocess_args,
Expand Down
12 changes: 12 additions & 0 deletions ml-agents-envs/mlagents_envs/tests/test_envs.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ def test_port_defaults(
assert expected == env.port


@mock.patch("mlagents_envs.environment.UnityEnvironment.executable_launcher")
@mock.patch("mlagents_envs.environment.UnityEnvironment.get_communicator")
def test_log_file_path_is_set(mock_communicator, mock_launcher):
mock_communicator.return_value = MockCommunicator()
env = UnityEnvironment(
file_name="myfile", worker_id=0, log_folder="./some-log-folder-path"
)
args = env.executable_args()
log_file_index = args.index("-logFile")
assert args[log_file_index + 1] == "./some-log-folder-path/Player-0.log"


@mock.patch("mlagents_envs.environment.UnityEnvironment.executable_launcher")
@mock.patch("mlagents_envs.environment.UnityEnvironment.get_communicator")
def test_reset(mock_communicator, mock_launcher):
Expand Down
11 changes: 9 additions & 2 deletions ml-agents/mlagents/trainers/learn.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,12 @@ def run_training(run_seed: int, options: RunOptions) -> None:
if options.env_path is None:
port = UnityEnvironment.DEFAULT_EDITOR_PORT
env_factory = create_environment_factory(
options.env_path, options.no_graphics, run_seed, port, options.env_args
options.env_path,
options.no_graphics,
run_seed,
port,
options.env_args,
os.path.abspath(run_logs_dir), # Unity environment requires absolute path
)
engine_config = EngineConfig(
options.width,
Expand Down Expand Up @@ -470,6 +475,7 @@ def create_environment_factory(
seed: int,
start_port: int,
env_args: Optional[List[str]],
log_folder: str,
) -> Callable[[int, List[SideChannel]], BaseEnv]:
if env_path is not None:
launch_string = UnityEnvironment.validate_environment_path(env_path)
Expand All @@ -489,8 +495,9 @@ def create_unity_environment(
seed=env_seed,
no_graphics=no_graphics,
base_port=start_port,
args=env_args,
additional_args=env_args,
side_channels=side_channels,
log_folder=log_folder,
)

return create_unity_environment
Expand Down
1 change: 1 addition & 0 deletions ml-agents/mlagents/trainers/tests/test_learn.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def test_bad_env_path():
seed=None,
start_port=8000,
env_args=None,
log_folder="results/log_folder",
)


Expand Down
17 changes: 13 additions & 4 deletions ml-agents/tests/yamato/scripts/run_llapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_run_environment(env_name):
file_name=env_name,
side_channels=[engine_configuration_channel],
no_graphics=True,
args=["-logFile", "-"],
additional_args=["-logFile", "-"],
)

try:
Expand Down Expand Up @@ -94,14 +94,23 @@ def test_closing(env_name):
"""
try:
env1 = UnityEnvironment(
file_name=env_name, base_port=5006, no_graphics=True, args=["-logFile", "-"]
file_name=env_name,
base_port=5006,
no_graphics=True,
additional_args=["-logFile", "-"],
)
env1.close()
env1 = UnityEnvironment(
file_name=env_name, base_port=5006, no_graphics=True, args=["-logFile", "-"]
file_name=env_name,
base_port=5006,
no_graphics=True,
additional_args=["-logFile", "-"],
)
env2 = UnityEnvironment(
file_name=env_name, base_port=5007, no_graphics=True, args=["-logFile", "-"]
file_name=env_name,
base_port=5007,
no_graphics=True,
additional_args=["-logFile", "-"],
)
env2.reset()
finally:
Expand Down