1
1
from __future__ import absolute_import
2
2
3
- import csv
4
3
from collections import defaultdict
5
- import logging
6
4
from multiprocessing import Process , Queue , cpu_count
7
- import warnings
8
-
5
+ from tempfile import NamedTemporaryFile
6
+ import csv
7
+ import logging
9
8
import tqdm
9
+ import warnings
10
10
11
+ from axelrod import on_windows
11
12
from .game import Game
12
13
from .match import Match
13
- from .match_generator import (RoundRobinMatches , ProbEndRoundRobinMatches ,
14
- SpatialMatches , ProbEndSpatialMatches )
14
+ from .match_generator import RoundRobinMatches , ProbEndRoundRobinMatches , SpatialMatches , ProbEndSpatialMatches
15
15
from .result_set import ResultSetFromFile , ResultSet
16
16
17
17
@@ -55,8 +55,25 @@ def __init__(self, players, match_generator=RoundRobinMatches,
55
55
self ._with_morality = with_morality
56
56
self ._logger = logging .getLogger (__name__ )
57
57
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
+
58
74
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 ):
60
77
"""
61
78
Plays the tournament and passes the results to the ResultSet class
62
79
@@ -71,8 +88,11 @@ def play(self, build_results=True, filename=None,
71
88
progress_bar : bool
72
89
Whether or not to create a progress bar which will be updated
73
90
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.
76
96
77
97
Returns
78
98
-------
@@ -82,18 +102,12 @@ def play(self, build_results=True, filename=None,
82
102
self .progress_bar = tqdm .tqdm (total = len (self .match_generator ),
83
103
desc = "Playing matches" )
84
104
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
95
107
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 :
97
111
warnings .warn ("Tournament results will not be accessible since build_results=False and no filename was supplied." )
98
112
99
113
if processes is None :
@@ -104,36 +118,40 @@ def play(self, build_results=True, filename=None,
104
118
if progress_bar :
105
119
self .progress_bar .close ()
106
120
107
- if filename :
121
+ # Make sure that python has finished writing to disk
122
+ if not in_memory :
108
123
self .outputfile .flush ()
109
- self .outputfile .close ()
110
124
111
125
if build_results :
112
126
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 ()
114
131
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 ):
116
134
"""
117
135
Build the result set (used by the play method)
118
136
119
137
Returns
120
138
-------
121
139
axelrod.BigResultSet
122
140
"""
123
- if self . filename is not None :
141
+ if not in_memory :
124
142
result_set = ResultSetFromFile (filename = self .filename ,
125
143
progress_bar = progress_bar ,
126
144
num_interactions = self .num_interactions ,
127
145
nrepetitions = self .repetitions ,
128
- keep_interactions = keep_interactions ,
129
146
players = [str (p ) for p in self .players ],
147
+ keep_interactions = keep_interactions ,
130
148
game = self .game )
131
149
self .outputfile .close ()
132
150
else :
133
151
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 )
137
155
return result_set
138
156
139
157
def _run_serial (self , progress_bar = False ):
@@ -159,13 +177,13 @@ def _run_serial(self, progress_bar=False):
159
177
160
178
def _write_interactions (self , results ):
161
179
"""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 )
166
184
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. """
169
187
for index_pair , interactions in results .items ():
170
188
for interaction in interactions :
171
189
row = list (index_pair )
@@ -178,7 +196,7 @@ def _write_to_file(self, results):
178
196
self .writer .writerow (row )
179
197
self .num_interactions += 1
180
198
181
- def _write_to_dict (self , results ):
199
+ def _write_interactions_to_dict (self , results ):
182
200
"""Write the interactions to memory"""
183
201
for index_pair , interactions in results .items ():
184
202
for interaction in interactions :
0 commit comments