LINUX.ORG.RU
ФорумTalks

Ненависть: не люблю Python

 ,


1

4

Как люди программируют на этом языке? ППЦ

По роду деятельности приходится изучать это и после Perl такая тоска накатывает шоппц.

В процессе изучения пытаюсь ради интереса попереписывать свои простейшие скрипты которыми пользуюсь повседневно.

Например есть у меня скрипт «если курсор мыши в правом верхнем углу экрана, то не давать включать screensaver».

В нем есть такой вот блок, определяющий подключенные мониторы и их конфиг:

#!/usr/bin/perl

use 5.20.0;
use YAML;

my %list;
open my $fh, '-|', '/usr/bin/xrandr';
while(<$fh>) {
    if (/^(\S+)\sconnected\s+(primary\s+)?(\d+)x(\d+)([+-]\d+)([+-]\d+)/) {
        $list{$1} = {
            name        => $1,
            w           => $3,
            h           => $4,
            x           => int($5),
            y           => int($6),
            primary     => $2 ? 1 : 0
        }
    }
}

print YAML::Dump \%list;

Запускаем - рассказывает о подключенных мониторах в машиночитаемом виде:

---
DP-1:
  h: 1440
  name: DP-1
  primary: 0
  w: 2560
  x: 2560
  y: 0
DP-2-1:
  h: 1440
  name: DP-2-1
  primary: 0
  w: 2560
  x: 0
  y: 0
eDP-1:
  h: 1080
  name: eDP-1
  primary: 1
  w: 1920
  x: 1280
  y: 1440

вроде что может быть проще?

Однако пытаемся переписать это на python и натыкаемся:

  1. что open - не умеет работать с пайпами
  2. что про пайпы велосипедят 100500 модулей
  3. что у строк есть 100500 методов, но работа с регекспами вынесена в какой-то ужасно сдизайненный модуль `re`
  4. что эти 20 строк кода на Python превратятся в 200

и как вы с этим живете, мозахисты?

★★

что open - не умеет работать с пайпами

subprocess.Popen

что эти 20 строк кода на Python превратятся в 200

Покажешь?

Perl

Соболезную. Для одностричников норм, но быстро превращается во write-only кашу. См. патч Бармина.

и как вы с этим живете, мозахисты?

Замечательно.

Deleted ()
Ответ на: комментарий от rsync

open my $fh, '-|', '/usr/bin/xrandr';

proc = subprocess.Popen(['/usr/bin/xrandr'], stdout=subprocess.PIPE)

while(<$fh>) {

proc.stdout.read()

Ы?

Deleted ()
Последнее исправление: ecko (всего исправлений: 1)
Ответ на: комментарий от Deleted

write-only кашу

это у питона

даже javascript позволяет писать

if (str.match(/regexp/)) {
  // бла
}

и только питон заставляет разбивать это на подоперации

и там где у других языков 1-2 строки у питона 20-30 именно write only

rsync ★★ ()
Ответ на: комментарий от rsync

Я просто ещё разок попрошу тот код, что у тебя получился на питоне. Пердеть в лужу каждый горазд, а ты код скинь.

Deleted ()

Practical Extraction and Reporting Language победил нормальный ЯП на синтетической задаче extraction и reporting? Кто бы мог подумать?!

t184256 ★★★★★ ()

Как люди программируют на этом языке?

Как обычно.

По роду деятельности приходится изучать это и после Perl такая тоска накатывает шоппц.

Смени род дейтельности. Он тебе явно не подходит. Если тоска уже сейчас накатывает, что будет потом?

Например есть у меня скрипт

Perl вырос из задачи обработки отчётов. Если задача сводится к обработке отчётов, он будет выигрывать в компактности кода.

i-rinat ★★★★★ ()
Ответ на: комментарий от rsync

Компиляция регулярного выражения в Python не обязательна и существует только для пущей скорости – чтобы в каком-нибудь цикле выражение компилировалось только один раз. А так… и где тут 20-30 строк?

if re.match(r"regex", str):
    # бла

Darth_Revan ★★★★★ ()
Последнее исправление: Darth_Revan (всего исправлений: 2)
Ответ на: комментарий от Darth_Revan

Подожди ты, он ещё не дошёл до шага, где нужно сделать import re, а ты ему пример использования приводишь.

grem ★★★★★ ()

Любой язык с нестрогой типизацией это плохо.

GblGbl ★★★★★ ()

А почему у тебя строки w и h дампятся так же, как и числа x и y?

deadNightTiger ★★★★ ()
Ответ на: комментарий от Darth_Revan

Оно и так один раз будет компилироваться. Просто иногда нужно передать куда-нибудь уже скомпилированную регулярку, например в монгу

needle = re.compile(re.escape(needle), re.IGNORECASE)
text = next(kcposts.aggregate([{'$match':{'text':{'$regex':         needle}}}, {'$sample': {'size':1}}])
pawnhearts ★★★★★ ()

200 строк

#!/usr/bin/env python3

import re
import subprocess
import sys
import yaml


RGX = re.compile(
    r'^(\S+)\sconnected\s+(primary\s+)?(\d+)x(\d+)([+-]\d+)([+-]\d+)')
out = subprocess.check_output(['/usr/bin/xrandr']).decode()
ret = {}
for line in out.splitlines():
    res = re.match(RGX, line)
    if res:
        ret[res.group(1)] = {
            'name': res.group(1),
            'w': int(res.group(3)),
            'h': int(res.group(4)),
            'x': int(res.group(5)),
            'y': int(res.group(6)),
            'primary': True if res.group(2) else False,
        }
yaml.dump(ret, sys.stdout, default_flow_style=False)

25 строк вместо 21. Вау.

Deleted ()
Ответ на: комментарий от deadNightTiger

Да, subprocess.run – это хорошо, я просто решил дать достаточно совместимое решение, чтобы не было возмущений у ТС, если у него более старая версия Python %).

Darth_Revan ★★★★★ ()

Прям уж таки 200?

#!/usr/bin/python2

import re
from subprocess import Popen, PIPE

randr=Popen("/usr/bin/xrandr",stdout=PIPE)
randr.wait()
for line in  randr.stdout.readlines():
	match=re.match(r"^(\S+)\sconnected\s+(primary\s+)?(\d+)x(\d+)([+-]\d+)([+-]\d+)",line)
	if match:
		p=match.groups()
		print "%s\n\tname: %s\n\tw: %s\n\th: %s\n\tx: %d\n\ty: %d\n\tprimary: %d\n" %(p[0],p[0],p[2],p[3],int(p[4]),int(p[5]),1 if p[1] else 0 )
Вывод:
DVI-I-0
	name: DVI-I-0
	w: 1280
	h: 1024
	x: 0
	y: 0
	primary: 1

Rupricht ★★ ()
Ответ на: 200 строк от Deleted
-out = subprocess.check_output(['/usr/bin/xrandr']).decode()
+out = subprocess.check_output(['/usr/bin/xrandr'], universal_newlines=True)
Darth_Revan ★★★★★ ()
Последнее исправление: Darth_Revan (всего исправлений: 1)
Ответ на: 200 строк от Deleted

Можно выиграть одну строчку на import sys (использовать print вместо stdout) :)

deadNightTiger ★★★★ ()
Ответ на: комментарий от deadNightTiger

Здесь нет объекта типа yaml, поэтому тут нужен именно yaml.dump в sys.stdout

UPD: если же говорить о JSON (а корректный JSON является корректным YAML), то можно (в данном случае) вывести и сырой дикт

Deleted ()
Последнее исправление: ecko (всего исправлений: 1)
Ответ на: комментарий от GblGbl

Любой язык с нестрогой типизацией это плохо.

разве у перла нестрогая типизация?

MyTrooName ★★★★★ ()
Ответ на: комментарий от pawnhearts

Оно и так один раз будет компилироваться.

Эм, Python нигде не будет запоминать результат компиляции, если ему прямо не сказать.
Прямо сейчас на всякий попробовал и убедился, что в длинном цикле компилированное регулярное выражение выполняется быстрее.

Darth_Revan ★★★★★ ()
Ответ на: комментарий от deadNightTiger

Тоже не знал :)

Теперь в моём сниппете уже 23 строчки.

Deleted ()
Ответ на: 200 строк от Deleted

Взял на заметку как можно затроллеть пипл, чтобы тебе переписали код на другой ЯП

goingUp ★★★★★ ()
Ответ на: комментарий от pawnhearts

Хм, действительно, сильная динамическая типизация.

Darth_Revan ★★★★★ ()

Предположу, что ТС искусно развёл всех, ибо ему изначально нужно было переписать этот write-only перл на пистон.

UVV ★★★★★ ()
Ответ на: комментарий от pawnhearts

Note: The compiled versions of the most recent patterns passed to re.compile() and the module-level matching functions are cached, so programs that use only a few regular expressions at a time needn’t worry about compiling regular expressions.

Есть такое.

import re
for i in range(0, 500000):
    if re.match(r"^w.*t$", "wut"):
        pass
real	0m0,865s
user	0m0,851s
sys	0m0,009s

import re
regex = re.compile(r"^w.*t$")
for i in range(0, 500000):
    if regex.match("wut"):
        pass
real	0m0,364s
user	0m0,356s
sys	0m0,008s
Но в чём подвох тогда?
Разрыв устойчивый. Python 3.6.5, x86-64.

Darth_Revan ★★★★★ ()
Последнее исправление: Darth_Revan (всего исправлений: 2)
Ответ на: комментарий от Darth_Revan

Незнаю. Я предположил, что в первом случае у тебя создается больше объектов. Но, вроде как, нет.

In [1]: import re

In [2]: z=re.match('w','wat')

In [3]: id(z.re)
Out[3]: 140421871269248

In [4]: z=re.match('w','wat')

In [5]: id(z.re)
Out[5]: 140421871269248

In [6]: z=re.match('w','wata')

In [7]: id(z.re)
Out[7]: 140421871269248

В любом случае, код читаемей когда регулярка под рукой, а не скомпилирована где-то в другом месте.

pawnhearts ★★★★★ ()
Ответ на: комментарий от deadNightTiger

В 3.7 предлагают делать subprocess.run(capture_output=True)

Вообще, check=True в данном случае не помешает (предполагается check_output'ом, да), ибо парсер совсем не учитывает возможность ошибки у xrandr.
Лучше уж необработанное исключение.

Darth_Revan ★★★★★ ()
Ответ на: комментарий от pawnhearts

В любом случае, код читаемей когда регулярка под рукой, а не скомпилирована где-то в другом месте.

А вот это не факт. Если регулярка достаточно головоломная то её замена на переменную с осмысленным именем может повысить читаемость кода

MrClon ★★★★★ ()
Ответ на: комментарий от Deleted

Уверен что хочешь увидеть ЭТО? Понедельник и без того день непростой

MrClon ★★★★★ ()
Ответ на: комментарий от MrClon

имхо если у тебя в коде головоломные регулярки, то ты что-то делаешь не так.

pawnhearts ★★★★★ ()
Ответ на: комментарий от pawnhearts

ИМХО примерно любая регулярка более головоломна чем осмыслено поименованная переменная. Другое дело что придумывание осмысленного имени для переменной может быть много более головоломным чем разбор тривиальной регулярки (пусть даже разбирать её придётся сотню раз)

MrClon ★★★★★ ()
Ответ на: комментарий от Darth_Revan
if re.match(r"regex", str):

этот код неработоспособен

rsync ★★ ()
Ответ на: комментарий от goingUp

Взял на заметку как можно затроллеть пипл, чтобы тебе переписали код на другой ЯП

Rust — говно! Попытался переписать linux kernel…

MrClon ★★★★★ ()
Ответ на: комментарий от grem

этот код неработоспособен

$ python3
Python 3.6.7 (default, Oct 21 2018, 08:08:16) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> if re.match(r'lo', 'Hello world'): print('ok')
... 
>>>
rsync ★★ ()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)