Skip to content

Commit f58c34b

Browse files
committed
Make temp file default: switch to mem if win
1 parent a28ed1e commit f58c34b

File tree

2 files changed

+56
-38
lines changed

2 files changed

+56
-38
lines changed

axelrod/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import absolute_import
22
import sys
33

4+
on_windows = sys.platform.startswith("win")
5+
46
# The order of imports matters!
57
from .actions import Actions, flip_action
68
from .random_ import random_choice, seed
@@ -16,5 +18,3 @@
1618
from .tournament import Tournament, ProbEndTournament, SpatialTournament, ProbEndSpatialTournament
1719
from .result_set import ResultSet, ResultSetFromFile
1820
from .ecosystem import Ecosystem
19-
20-
on_windows = sys.platform.startswith("win")

axelrod/tournament.py

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
from __future__ import absolute_import
22

3-
import csv
43
from collections import defaultdict
5-
import logging
64
from multiprocessing import Process, Queue, cpu_count
7-
import warnings
8-
5+
from tempfile import NamedTemporaryFile
6+
import csv
7+
import logging
98
import tqdm
9+
import warnings
1010

11+
from axelrod import on_windows
1112
from .game import Game
1213
from .match import Match
13-
from .match_generator import (RoundRobinMatches, ProbEndRoundRobinMatches,
14-
SpatialMatches, ProbEndSpatialMatches)
14+
from .match_generator import RoundRobinMatches, ProbEndRoundRobinMatches, SpatialMatches, ProbEndSpatialMatches
1515
from .result_set import ResultSetFromFile, ResultSet
1616

1717

@@ -55,8 +55,25 @@ def __init__(self, players, match_generator=RoundRobinMatches,
5555
self._with_morality = with_morality
5656
self._logger = logging.getLogger(__name__)
5757

58+
def setup_output_file(self, filename=None, in_memory=False):
59+
"""Open a CSV writer for tournament output."""
60+
if in_memory:
61+
self.interactions_dict = {}
62+
self.writer = None
63+
else:
64+
if filename:
65+
self.outputfile = open(filename, 'w')
66+
else:
67+
# Setup a temporary file
68+
self.outputfile = NamedTemporaryFile(mode='w')
69+
filename = self.outputfile.name
70+
self.writer = csv.writer(self.outputfile, lineterminator='\n')
71+
# Save filename for loading ResultSet later
72+
self.filename = filename
73+
5874
def play(self, build_results=True, filename=None,
59-
processes=None, progress_bar=True, keep_interactions=False):
75+
processes=None, progress_bar=True,
76+
keep_interactions=False, in_memory=False):
6077
"""
6178
Plays the tournament and passes the results to the ResultSet class
6279
@@ -71,8 +88,11 @@ def play(self, build_results=True, filename=None,
7188
progress_bar : bool
7289
Whether or not to create a progress bar which will be updated
7390
keep_interactions : bool
74-
Whether or not to save the interactions to memory. Only relevant
75-
when writing to file.
91+
Whether or not to load the interactions in to memory
92+
in_memory : bool
93+
By default interactions are written to a file.
94+
If this is True they will be kept in memory.
95+
This is not advised for large tournaments.
7696
7797
Returns
7898
-------
@@ -82,18 +102,12 @@ def play(self, build_results=True, filename=None,
82102
self.progress_bar = tqdm.tqdm(total=len(self.match_generator),
83103
desc="Playing matches")
84104

85-
if filename is not None:
86-
self.outputfile = open(filename, 'w')
87-
self.writer = csv.writer(self.outputfile, lineterminator='\n')
88-
self.filename = filename
89-
self.interactions_dict = None
90-
else:
91-
self.outputfile = None
92-
self.writer = None
93-
self.filename = None
94-
self.interactions_dict = {}
105+
if on_windows and (filename is None):
106+
in_memory = True
95107

96-
if (not build_results) and (filename is None):
108+
self.setup_output_file(filename, in_memory)
109+
110+
if not build_results and not filename:
97111
warnings.warn("Tournament results will not be accessible since build_results=False and no filename was supplied.")
98112

99113
if processes is None:
@@ -104,36 +118,40 @@ def play(self, build_results=True, filename=None,
104118
if progress_bar:
105119
self.progress_bar.close()
106120

107-
if filename:
121+
# Make sure that python has finished writing to disk
122+
if not in_memory:
108123
self.outputfile.flush()
109-
self.outputfile.close()
110124

111125
if build_results:
112126
return self._build_result_set(progress_bar=progress_bar,
113-
keep_interactions=keep_interactions)
127+
keep_interactions=keep_interactions,
128+
in_memory=in_memory)
129+
else:
130+
self.outputfile.close()
114131

115-
def _build_result_set(self, progress_bar=True, keep_interactions=False):
132+
def _build_result_set(self, progress_bar=True, keep_interactions=False,
133+
in_memory=False):
116134
"""
117135
Build the result set (used by the play method)
118136
119137
Returns
120138
-------
121139
axelrod.BigResultSet
122140
"""
123-
if self.filename is not None:
141+
if not in_memory:
124142
result_set = ResultSetFromFile(filename=self.filename,
125143
progress_bar=progress_bar,
126144
num_interactions=self.num_interactions,
127145
nrepetitions=self.repetitions,
128-
keep_interactions=keep_interactions,
129146
players=[str(p) for p in self.players],
147+
keep_interactions=keep_interactions,
130148
game=self.game)
131149
self.outputfile.close()
132150
else:
133151
result_set = ResultSet(players=[str(p) for p in self.players],
134-
interactions=self.interactions_dict,
135-
progress_bar=progress_bar,
136-
game=self.game)
152+
interactions=self.interactions_dict,
153+
progress_bar=progress_bar,
154+
game=self.game)
137155
return result_set
138156

139157
def _run_serial(self, progress_bar=False):
@@ -159,13 +177,13 @@ def _run_serial(self, progress_bar=False):
159177

160178
def _write_interactions(self, results):
161179
"""Write the interactions to file or to a dictionary"""
162-
if self.interactions_dict is not None:
163-
self._write_to_dict(results)
164-
elif self.writer is not None:
165-
self._write_to_file(results)
180+
if self.writer is not None:
181+
self._write_interactions_to_file(results)
182+
elif self.interactions_dict is not None:
183+
self._write_interactions_to_dict(results)
166184

167-
def _write_to_file(self, results):
168-
"""Write the interactions to csv file"""
185+
def _write_interactions_to_file(self, results):
186+
"""Write the interactions to csv."""
169187
for index_pair, interactions in results.items():
170188
for interaction in interactions:
171189
row = list(index_pair)
@@ -178,7 +196,7 @@ def _write_to_file(self, results):
178196
self.writer.writerow(row)
179197
self.num_interactions += 1
180198

181-
def _write_to_dict(self, results):
199+
def _write_interactions_to_dict(self, results):
182200
"""Write the interactions to memory"""
183201
for index_pair, interactions in results.items():
184202
for interaction in interactions:

0 commit comments

Comments
 (0)