Ответ Шона Чина хороший, но одна проблема с ним заключается в том, что если вы пропустите конкретный элемент в своем формате (как в его втором примере, который имеет только часы и минуты, а не дни или секунды), то это время исчезнет. из вашего результата. Вы можете изменить его, чтобы устранить эту проблему и получить более точные результаты, обрабатывая только те ключевые слова, которые фактически отображаются в строке формата.
class DeltaTemplate(Template):
delimiter = '%'
def strfdelta(tdelta, fmt):
d = {}
l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
rem = int(tdelta.total_seconds())
for k in ( 'D', 'H', 'M', 'S' ):
if "%{}".format(k) in fmt:
d[k], rem = divmod(rem, l[k])
t = DeltaTemplate(fmt)
return t.substitute(**d)
Использование:
>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
44 hours and 18 to go
Хотя форматирование жестко, поскольку вы не можете применить какие-либо строки преобразования и получить такие уродливые вещи, как это:
>>> delta_obj = timedelta(minutes=5, seconds=2)
>>> print strfdelta(delta_obj, "%H:%M:%S")
0:5:2
Однако вы можете воспользоваться тем же подходом и применить его к string.Formatter вместо string.Template и получить что-то намного лучше.
from string import Formatter
def strfdelta(tdelta, fmt):
f = Formatter()
d = {}
l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
k = map( lambda x: x[1], list(f.parse(fmt)))
rem = int(tdelta.total_seconds())
for i in ('D', 'H', 'M', 'S'):
if i in k and i in l.keys():
d[i], rem = divmod(rem, l[i])
return f.format(fmt, **d)
Использование:
>>> delta_obj = timedelta(days=1, hours=20, minutes=18, seconds=12)
>>> print strfdelta(delta_obj, "{D} days {H}:{M}:{S}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{H} hours and {M} to go")
44 hours and 18 to go
>>> delta_obj = timedelta(minutes=5, seconds=2)
>>> print strfdelta(delta_obj, "{H:02}h{M:02}m{S:02}s")
00h05m02s
>>> print strfdelta(delta_obj, "{H:02}:{M:02}:{S:02}")
00:05:02
Если вы проверите exe-файлы с помощью ILDASM, вы увидите разницу в манифесте (найдите «подсистему»).
В приложении Winforms:
.subsystem 0x0002 // WINDOWS_GUI
В консольное приложение:
.subsystem 0x0003 // WINDOWS_CUI
В коде IL может быть больше различий.
Когда дело доходит до того, что заставляет компилятор выдавать это по-разному в двух случаях, это контролируется значением OutputType файла проекта:
Приложение Winforms:
<OutputType>WinExe</OutputType>
В консольном приложении:
<OutputType>Exe</OutputType>
Из любопытства я также проверил это значение для проекта библиотеки классов:
<OutputType>Library</OutputType>
В свойствах проекта, вкладка приложения, тип вывода вы можете установите "Приложение Windows" или "Консольное приложение".
Я считаю, что за кулисами VS делает именно то, что Фредрик представил в своем сообщении.
Кроме того, если установить его в Консольное приложение, вы увидите черное консольное приложение для проекта Windows Forms.
Под капотом нет никакой разницы между winform и console exe, за исключением флага в PE-заголовке: «Мне нужна консоль». Заголовок PE не контролируется вашим C # (так как это вещь компиляции, а не время выполнения), поэтому вместо этого он определяется в файле проекта (
).
Или в командной строке ( csc / target: exe
vs csc /target:winexe[1113427 provided).[1210 impression Скорее всего, они могли использовать атрибут уровня сборки, который перехватил компилятор, но действительно ли это помогло? Наверное, нет.
Если вы посмотрите в файл проекта (csproj), вы увидите, что цель определена там как консоль или приложение Windows.