Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/agilepy/lib_base/processes.py
169689 views
1
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
2
# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.
3
# SUMOPy module
4
# Copyright (C) 2012-2021 University of Bologna - DICAM
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file processes.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
20
import subprocess
21
import os
22
import sys
23
import types
24
import pickle
25
26
27
#SUMOPYDIR = os.path.join(os.path.dirname(__file__),"..")
28
#TOOLSDIR = os.path.join(SUMOPYDIR,"..")
29
30
#APPDIR = os.path.join(os.path.dirname(__file__),"..")
31
32
33
import classman as cm
34
from misc import filepathlist_to_filepathstring, filepathstring_to_filepathlist, ff, P
35
36
37
# p = psutil.Process(the_pid_you_want) !!
38
# print p.status
39
# if p.status == psutil.STATUS_ZOMBIE:
40
41
##processlist = psutil.get_process_list()
42
##
43
# for p in processlist:
44
# if psutil.pid_exists(p.pid):
45
# print ' pid = ',p.pid
46
# print ' name =',p.name
47
# print ' running =',p.is_running()
48
# print ' path =',p.path
49
# print ' cmdline',p.cmdline
50
##
51
##
52
##cmd = 'nohup sumo --no-step-log --no-duration-log --no-warnings --step-length %.3f -c %s'%(time_simstep, filepath_netconfig)
53
##
54
# print '\n Starting command:',cmd
55
##p = subprocess.Popen(cmd, shell=True)
56
# print "p.pid",p.pid, "p.poll=",p.poll()
57
# p.wait()
58
# print '\n\nreturncode',p.poll(),p.returncode
59
# print 'p.stdout=\n', p.stdout
60
# call(cmd)
61
62
# in windows : start command3
63
64
65
def call(cmd):
66
"""
67
Calls a sytem commend lime. Returns 1 if executed successfully.
68
"""
69
# ensure unix compatibility
70
print(cmd)
71
# if isinstance(cmd, str):
72
# cmd = filter(lambda a: a!='', cmd.split(' '))
73
# subprocess.call(cmd)
74
p = subprocess.Popen(cmd, shell=True)
75
p.wait()
76
return p.returncode == 0
77
78
79
class Process(cm.BaseObjman):
80
def __init__(self, ident, **kwargs):
81
self._init_common(ident, **kwargs)
82
83
def _init_common(self, ident, parent=None, name=None, **kwargs):
84
self._init_objman(ident=ident, parent=parent, name=name, **kwargs)
85
attrsman = self.set_attrsman(cm.Attrsman(self))
86
self.optiongroupnames = ['options']
87
#self.net = attrsman.add( cm.ObjConf( network.Network(self) ) )
88
self.status = attrsman.add(cm.AttrConf(
89
'status', 'preparation',
90
groupnames=['_private', 'parameters'],
91
perm='r',
92
name='Status',
93
info='Process status: preparation-> running -> success|error.'
94
))
95
#self._logger.w(self.get_name(), key='action')
96
#self._logger.w('Prepare', key='message')
97
98
def _set_status(self, status):
99
self.status = status
100
101
def get_status(self):
102
return self.status
103
104
def get_kwoptions(self):
105
return self.get_attrsman().get_group_attrs('options')
106
107
def run(self):
108
if self.is_ready():
109
logger = self.get_logger()
110
self.status = 'running'
111
logger.start('Run process: %s' % self.get_name())
112
113
#logger.w('start', key='message')
114
#
115
ans = self.do()
116
#
117
#logger.w(self.status, key='message')
118
if ans == True:
119
self.status = 'success'
120
else:
121
self.status = 'error'
122
logger.stop('Finished %s with status %s.' % (self.get_name(), self.status))
123
124
return self.status == 'success'
125
# f self.status == 'error':
126
# return True
127
# self.status = 'success' # self.status = 'error'
128
# return True
129
else:
130
logger.stop('Cannot start %s.' % (self.get_name(),))
131
return False
132
133
def aboard(self):
134
self.status = 'aboarded'
135
136
def do(self):
137
#self.status = 'success'
138
return True
139
140
def update_params(self):
141
"""
142
Make all parameters consistent.
143
example: used by import OSM to calculate/update number of tiles
144
from process dialog
145
"""
146
pass
147
148
def is_ready(self):
149
"""
150
Returns True if process is ready to run.
151
152
"""
153
return True
154
155
def save_options(self, filepath):
156
optiondata = {}
157
for attrconf in self.get_attrsman().get_configs(filtergroupnames=self.optiongroupnames):
158
optiondata[attrconf.attrname] = attrconf.get_value()
159
160
cm.save_obj(optiondata, filepath, is_not_save_parent=False)
161
162
try:
163
f = open(filepath, 'wb')
164
except:
165
print 'WARNING in save: could not open', filepath
166
return False
167
168
# print ' before',is_not_save_parent,parent,obj.parent
169
pickle.dump(optiondata, f, protocol=2)
170
f.close()
171
172
def load_options(self, filepath):
173
try:
174
f = open(filepath, 'rb')
175
except:
176
print 'WARNING in load_options: could not open', filepath
177
return None
178
179
# try:
180
# print ' pickle.load...'
181
optiondata = pickle.load(f)
182
f.close()
183
184
attrsman = self.get_attrsman()
185
for attrname, value in optiondata.iteritems():
186
if attrsman.has_attrname(attrname):
187
attrsman.get_config(attrname).set_value(value)
188
189
190
class Options:
191
"""
192
Dummy option class to fake option parsing
193
"""
194
195
def __init__(self, **kwargs):
196
self._optionattrs = []
197
self._cmlvaluemaps = []
198
self._transdir = {}
199
self._filepathattrs = []
200
for attr, value in kwargs.iteritems():
201
self.add_option(attr, value)
202
203
def add_option(self, attr='', value='', cml=None,
204
is_filepath=False, cmlvaluemap=None):
205
setattr(self, attr, value)
206
self._optionattrs.append(attr)
207
self._cmlvaluemaps.append(cmlvaluemap)
208
if cml is not None:
209
self._transdir[attr] = cml
210
if is_filepath:
211
self._filepathattrs.append(attr)
212
213
def set_transdir(self, **transdir):
214
"""
215
Sets a dictionary to translate python compatible
216
option names into the command line optionnames,
217
only in case the command line options are not identical
218
with python attributes (for example if
219
command line options contain '.' or '-').
220
Format of transdir is python attribute as key and
221
command line option (as string, WITH preceeding'--') as value.
222
223
"""
224
self._transdir = transdir
225
226
def get_optionstring(self):
227
# print 'get_optionstring'
228
s = ''
229
for attr, cmlvaluemap in zip(self._optionattrs, self._cmlvaluemaps):
230
value = getattr(self, attr)
231
cmlattr = self._transdir.get(attr, attr)
232
is_continue = True
233
if cmlvaluemap is not None:
234
if cmlvaluemap.has_key(value):
235
is_continue = False # take value from mapping
236
if P == '"': # windows
237
s += ' '+cmlattr+' "%s"' % cmlvaluemap[value]
238
else:
239
s += ' '+cmlattr+" '%s'" % cmlvaluemap[value]
240
# print ' option',attr,cmlattr, 'cmlvaluemap',cmlvaluemap
241
242
if is_continue:
243
244
if attr in self._filepathattrs:
245
if value != '':
246
s += ' '+cmlattr+' %s' % filepathlist_to_filepathstring(value.split(','))
247
elif type(value) == types.BooleanType:
248
if value:
249
s += ' '+cmlattr
250
elif type(value) in [types.StringTypes, types.UnicodeType]:
251
if P == '"': # windows
252
s += ' '+cmlattr+' "%s"' % value
253
else:
254
s += ' '+cmlattr+" '%s'" % value
255
else:
256
s += ' '+cmlattr+' %s' % value
257
return s
258
259
260
class CmlMixin:
261
def init_cml(self, command, is_run_background=False, is_nohup=False, workdirpath=None):
262
263
self.optiongroupname = 'cml-options'
264
self.optiongroupnames.append(self.optiongroupname)
265
attrsman = self.get_attrsman()
266
self.pathmetatypes = ['filepath', 'dirpath', 'filepaths', 'dirpaths']
267
self.workdirpath = workdirpath
268
self._command = attrsman.add(cm.AttrConf(
269
'_command', command,
270
groupnames=['_private'],
271
perm='r',
272
name='command',
273
info='Command to be executed.'
274
))
275
self.pid = attrsman.add(cm.AttrConf(
276
'pid', -1,
277
groupnames=['_private'],
278
perm='r',
279
name='Process ID',
280
info="The system's Process ID",
281
))
282
283
self.is_run_background = attrsman.add(cm.AttrConf(
284
'is_run_background', is_run_background,
285
groupnames=['parameters', 'advanced'],
286
perm='rw',
287
name='Run in background',
288
info='If set, process will run in background.',
289
))
290
291
self.is_nohup = attrsman.add(cm.AttrConf(
292
'is_nohup', is_nohup,
293
groupnames=['parameters', 'advanced', ],
294
perm='rw',
295
name='No hangup',
296
info="""If set, process will run in the background and will continue to run after logout. (Currently on UNIX platforms only.) """,
297
))
298
299
def add_option(self, option, value, **kwargs):
300
kwargs0 = {'cml': None,
301
'groupnames': [],
302
'perm': 'rw',
303
'is_save': True,
304
'name': None,
305
'info': '',
306
}
307
308
kwargs0.update(kwargs)
309
if not (self.optiongroupname in kwargs0['groupnames']):
310
kwargs0['groupnames'] += [self.optiongroupname]
311
312
# print '\nadd_option', option, value,kwargs0
313
default = self.get_attrsman().add(cm.AttrConf(option, value, **kwargs0))
314
setattr(self, option, default)
315
316
def get_options(self):
317
print '\nget_options'
318
options = Options()
319
for attrconfig in self.get_attrsman().get_configs(is_all=True):
320
if self.optiongroupname in attrconfig.groupnames:
321
print ' option', attrconfig.attrname, attrconfig.groupnames, 'is path', attrconfig.get_metatype() in self.pathmetatypes, 'has cmlmap', hasattr(attrconfig, 'cmlvaluemap')
322
is_enabled = True
323
if hasattr(attrconfig, 'is_enabled'):
324
print ' is_enabled=', attrconfig.is_enabled(self), attrconfig.get_value()
325
is_enabled = attrconfig.is_enabled(self)
326
if is_enabled: # disabeled options are simply not added
327
if hasattr(attrconfig, 'cmlvaluemap'):
328
cmlvaluemap = attrconfig.cmlvaluemap
329
else:
330
cmlvaluemap = None
331
is_filepath = attrconfig.get_metatype() in self.pathmetatypes
332
options.add_option(attrconfig.attrname, attrconfig.get_value(), attrconfig.cml,
333
is_filepath=is_filepath, cmlvaluemap=cmlvaluemap)
334
335
return options
336
337
def print_options(self):
338
print 'Options of process ident:', self.ident
339
print ' Keywordoptions:'
340
for attrconfig in self.get_attrsman().get_configs(filtergroupnames=[self.optiongroupname]):
341
print ' ', attrconfig.attrname, '=', attrconfig.get_value()
342
343
def reset_cml(self, cml):
344
self._command = cml
345
346
def get_cml(self, is_changecwd=False, is_without_command=False):
347
"""
348
Returns commandline with all options.
349
To be overridden by costum class.
350
"""
351
# is_changecwd is obsolete, chenge in different directory
352
# if self.workdirpath is not None
353
options = self.get_options()
354
optionstr = options.get_optionstring()
355
print 'get_cml command', self._command, 'workdirpath', self.workdirpath
356
if True: # self.workdirpath is None:
357
if is_without_command:
358
cml = optionstr
359
else:
360
cml = P+self._command+P + optionstr
361
else:
362
cml = 'cd '+P+self.workdirpath+P+' ;'\
363
+ P+self._command+P + optionstr
364
365
# print ' now call get_optionstring',options.get_optionstring
366
return cml
367
368
def run_cml(self, cml=None):
369
if cml is None:
370
cml = self.get_cml()
371
attrsman = self.get_attrsman()
372
if self.workdirpath is not None:
373
wd = self.workdirpath
374
# os.chdir(self.workdirpath)
375
self._subprocess = subprocess.Popen(cml, shell=True, cwd=wd)
376
377
else:
378
wd = os.getcwd()
379
self._subprocess = subprocess.Popen(cml, shell=True)
380
381
attrsman.pid.set(self._subprocess.pid)
382
attrsman.status.set('running')
383
print 'run_cml cml=', cml
384
print ' pid = ', self.pid, 'cwd', wd
385
if not self.is_run_background:
386
self._subprocess.wait()
387
# if self.workdirpath is not None:
388
# os.chdir(wd)
389
390
if self._subprocess.returncode == 0:
391
attrsman.status.set('success')
392
return True
393
394
else:
395
attrsman.status.set('error')
396
return False
397
398
399
# print '\n Starting command:',cmd
400
##p = subprocess.Popen(cmd, shell=True)
401
# print "p.pid",p.pid, "p.poll=",p.poll()
402
# p.wait()
403
# print '\n\nreturncode',p.poll(),p.returncode
404
# print 'p.stdout=\n', p.stdout
405
# call(cmd)
406
###############################################################################
407
if __name__ == '__main__':
408
"""
409
Test
410
"""
411
412
# for testing only to get the object browser...
413
sys.path.append(os.path.join(APPDIR, "lib_meta_wx"))
414
415