#internals-and-peps

1 messages · Page 85 of 1

junior wedge
#

Oh, my bad

#

I did repost in data-science earlier, but i thought it'd fit in this channel as well

stoic bone
#

But what about discussions about discussions about python itself?

#

#meta!

unkempt rock
#

can anyone help me with my cw?

raven ridge
mint forge
#

What do you guys think about PYTHONPATH

raven ridge
#

what about it?

unkempt rock
#

Anyone here for urgent help ?

undone hare
cursive urchin
#

I'm currently doing the Python challenges on Edabit. I can do all of the "very easy" challenges but none of the "easy" ones (Maybe a couple). Does somebody have any advice for me?

unkempt rock
#

keep doing them

#

also read other peoples solutions

drifting coyote
#

i recommend reading a book or watching videos , googling stuff you need.
what I did when doing edabit and I did not know how to do something for example check if an item is in a list? I would google: python check if item in list and then from there on code with some forums on my side to get more knowledge on certain things

#

and it will get you some basic knowledge but after a while I found the challenges a bit repetitive and I could solve them but only with basic knowledge, like I would have 10 lines of code when the top solution had just 2 or 3, now I am working on automatetheboringstuff and it taught me a lot already. The book was easier because I knew a few concepts already but you learn shorter ways of solving stuff

#

because you can solve something with 10 for loops and if else statements but there is also quicker ways

coral goblet
#

Is it possible to detect http requests / other requests using sockets? I am making a "firewall" (just for fun) that scans all incoming http requests and i can't seem to find anything about this

tulip hazel
#

Um unsure if this is an advanced discussion, is not exactly a "help me with my code" question but im wondering if people that have worked with tf-keras models alot can answer.
I recently extended a few keras-tf GRU seq2seq models for generating predictions in a particular nmt application. I increased both data inputs and parameters, and ofcourse dataset size increased considerably, initially it takes about 45 gig of ram which is expected from the unpickled data.

What i find peculiar is that the ** ram used is increased by 4 gigs every epoch** ( an epoch is about 7 hours on a titan for me). As I understand, weights should update not occupy more memory every epoch. Is this standard behavior anyone has noticed or is it an outlier behavior I should try to fix for model? ( I took the layers from published sources/repos)

signal bear
#

how do you guys avoid circular imports

#

this is my first large scale python app

#

and i never really appreciated how difficult it was to manage these different modules

#

i get that it's project specific, and this is my first time so I'm not taking ti too personal

#

but idk how to avoid these circular dependencies

grave jolt
#

@signal bear if you have a specific issue, maybe I could help you in a help channel

signal bear
#

@grave jolt ping me if you're around I'm going to be working for a while, we can jump into a help channel

grave jolt
heady mauve
#

I am looking to create a game that allows users to write Python code to interact with objects in the game. How can I limit the user's code to interacting only with a subset of the game objects and prevent it from accessing files, system DLLs, the internet, etc?

sage tundra
#

to a first approximation, you can't. Like, there are projects like https://doc.pypy.org/en/latest/sandbox.html (that's probably the best of the bunch), but none of them have seen the kind of sustained attention from security researcher that should make you confident they're reasonably air-tight.

#

Even if they were perfect, what about the next Row-hammer, Spectre, or Meltdown?

grave jolt
#

You could run Python in a jailed process using something like nsjail and communicate between them using sockets, but I'm not sure what alternatives there are for Windows

#

I'm a weird person, so I would just write my own game-specific scripting language 😛

past valve
#

Does anyone have any good examples of packages that use the current gold-standard of python packaging but ships a native extension module that requires a custom build step? (in my case compiling something via rust/cargo)

radiant fulcrum
#

basically the only reason why Lua was made and used by roblox and others

#

@past valve that would want something like Rust-Setuptools but you can just use maturin to handle producing the binary wheels

#

if you want your extension to be easy for others to install prebuilt wheels is the way

past valve
#

@radiant fulcrum right. so setuptools is basically what i'm using currently but i'm noticing the ecosystem is moving into new directions

#

trying to re-evaluate if the approach is still sane

radiant fulcrum
#

plain setup tools or rust-setuptools

sacred yew
past valve
#

@radiant fulcrum wasn't the whole point of pyproject.toml to enable non setuptools based build systems?

#

also from what i can tell pip's editable installs are completely broken when pyproject.toml is used

radiant fulcrum
#

seems like you're overcomplicating stuff

#

Rust-Setuptools handles all the building itself (But generally its bad for the developer cuz they might need to install rust to install).

the 'gold standard' for a native lib would be a coverage of pre-built wheels supporting from the current supported python versions e.g. 3.6 -> 3.9,

Though alot of this depends on if you're using a system like PyO3 or Rust-Cpython you can also use maturin which does all the handling of wheels and pushing to pypi for you which makes setting up cli to auto build wheels a breeze

sage tundra
#

@grave jolt how would you defend against attacks like meltdown/spectre/rowhammer? 🙂

grave jolt
#

well... if your low-level stack is exploited, you're screwed

hollow tangle
#

does anyone have experience with the markdown library in python?

grave jolt
#

like, the possibility of a nuclear war doesn't prevent us from discussing safety of elevators

grave jolt
past valve
#

@radiant fulcrum i'm not sure how i'm "overcomplicating". setuptools is awful to hook

#

my goal was to reevaluate where the community stands at the moment with regards to external build systems since i haven't updated my stuff in close to three years

#

and it's my understanding from conversations about a year ago that this ecosystem is moving

#

in particular there are people using non setuptools to build wheels

radiant fulcrum
#

for rust that would be maturin

grave jolt
radiant fulcrum
#

literally maturin build compiles and packages the wheels

sage tundra
#

I'm not sure what the threat model of the Lua library as used in games is. 🙂

radiant fulcrum
#

its generally in a VM so not much it wants to care about

heady mauve
radiant fulcrum
#

then run it in something like a Jail e.g. NSJail (Like @fallen slate 's eval does) or a VM etc...

heady mauve
#

ok thanks fix error

past valve
#

@radiant fulcrum thanks, will look at that

radiant fulcrum
#

pretty sure it supports CFFI, PyO3 and Rust-Cpython now

#

so that should be all bases really

past valve
#

i don't care so much about rust in this case as trying to understand how the tools are set up

radiant fulcrum
#

cant really explain but on that front generally confused the shit out of me until they released maturin making it alot cleaner

past valve
#

i wrote a library a few years ago called milksnake for our purposes

#

which is an awful hack on top of setuptools

#

trying to re-evaluate this now

torpid bridge
#

From milksnake, compared to maturin, things I like are the python interface (rather than TOML for maturin), and the flexibility. The interface seems much cleaner and nicer than maturin, and I can forsee things like nim support utilizing https://github.com/yglukhov/nimpy, or other tools that at the moment require dedicated setuptools integration, (such as nython, to match nim and nimpy, which is used through setuptools as a manual build step, but could instead just be a few functions via milksnake.

#

Something you could try to do is advertise/finalize the capability to attach various software directly to python. Depending on language (go has cgo, rust cbindgen, nim compiles directly to c) it may end up actually very easy to convert an existing codebase to a cffi python extension.

spark nest
#

If anyone is interested, I'm working on a project to JIT compile Python bytecode to native machine code. Its a "reimagining" of sth started a few years ago by brett cannon. But I've rewritten a lot of the core and got it pip-installable. Its very alpha but the plan is to stabilise the core concept then start to implement JIT optimizations https://github.com/tonybaloney/Pyjion

#

I'm curious for any opinions on what JIT optimisations would be most impactful. Considering other JITs (PyPY, Numba) that already exist

torpid bridge
#

I think what python would want the most is some pointer-chasing improvements and method optimizations via heavy inlining. For example, there's a lot of steps between set() & set() that could probably be inlined quite heavily. I'm not sure how far python's own compilation process takes that, but for user-driven code you're usually not monkeypatching these things in after you start using the class, so a lot of method lookups could be inlined for significant speed boosts

grave jolt
#

Maybe one could enable some promise that you don't override builtins in a module? (and if it's broken, the program crashes or it's undefined behavior (i.e. the builtin is used instead of your object anyway))

#

or is that... too aggressive?

mint forge
#

how is being able to override the builtins in a module bad thing, that u would want to avoid it?

grave jolt
mint forge
#

o

grave jolt
#

So it's not that patching built-ins is evil (although it's very confusing, and I haven't ever had a reason to do that), but promising not to do that can allow for an optimization.

grave jolt
#

!e

import dis
import builtins

def nail(**names):
    def decorator(fn):
        code = fn.__code__.co_code
        consts = fn.__code__.co_consts
        positions = {}
        for instr in [*dis.get_instructions(fn)][::-1]:
            if instr.opname == "LOAD_GLOBAL" and instr.argval in names:
                if instr.argval not in positions:
                    positions[instr.argval] = len(consts)
                    consts += (names[instr.argval],)
                pos = positions[instr.argval]
                code = code[:instr.offset] + bytes([dis.opmap["LOAD_CONST"], pos]) + code[instr.offset+2:]
        fn.__code__ = fn.__code__.replace(co_code=code, co_consts=consts)
        return fn
    return decorator

nail_builtins = nail(**builtins.__dict__)

@nail_builtins
def f():
    for i, x in enumerate("abcd"):
        print(i, x)

f()
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 | 0 a
002 | 1 b
003 | 2 c
004 | 3 d
grave jolt
#

basically, some globals are replaced with constants

#

but this doesn't work if the total number of constants in a function becomes 256 or more

safe hedge
grave jolt
#

pyright supports recursive type aliases 😛

#

maybe you could make a Protocol

brave badger
unkempt rock
#

how to solve this??? 😭

mint forge
#

@unkempt rock not the correct channel for that

safe hedge
brave badger
#

It's a lot of boilerplate for the sake pf type safety, that's for sure

peak spoke
dense bay
#

^^

raven ridge
#

You need to opt out of that optimization if you want full Python compatibility

high solar
#

How many of you are using python as first language ?

#

It’s a good choice to using python as first language? I am configured when I using it as first language for 5 years.

undone hare
#

It (almost) was my first language, and I think it is a really good choice

high solar
#

@undone hare It’s using in your job?

undone hare
#

I don't have a job, I'm still at school :D

high solar
#

okay ~

#

Didn’t need to worries about life

#

I am enjoying before either

past sail
#

Review it please

high solar
#

@past sail 👍💯

steep barn
#

Guys, I have a question:
Lets say i define a class

class a:
  def init(self, a = 1, b = 2, c = 3, d = 4, e = 5):
    self.a = a
    self.b = b
    self.c = c
    self.d = d
    self.e = e

Now I insatiate the class two time like this:

instance1 = a()
instance2 = a(c = 5, e = 1)

Now is there a way to find out difference between these 2 objects?
by difference i mean to find out what values are different in instance instance2 as compare to default value instance instance1

past sail
past sail
steep barn
undone hare
#

You can get all the attributes of a class as a (key, value) using my_object.__dict__.items()

deft pagoda
#

you could also get signature of the class with inspect.signature --- run through the class dict and the instance dict and the signature to pick out which attributes aren't default

grave jolt
#

I tried to nail everything recursively in lark-parser -- didn't change the performance a slightest bit for my program using it. I guess it's not important at all for that particular library, I'll test some more.

safe hedge
#

So @unkempt rock and I have just been messing around in off-topic and starting with:

In [16]: %timeit max([len(x) for x in lol])
10.2 µs ± 668 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [17]: %timeit max(len(x) for x in lol)
12.1 µs ± 66.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

We ended up at:

>>> timeit.timeit("[n for n in [i for i in range(100000)]]", setup="import random", number=10000)
52.70060166100029
>>> timeit.timeit("[n for n in (i for i in range(100000))]", setup="import random", number=10000)
67.0565495410001

And can someone explain why the generator expression is slower?

grave jolt
#

A generator has to jump back and forth between the generator frame and the outer frame (it has to handle the mechanics of yield properly), while a list comprehension just creates a list in a single loop -- that's my guess on why

#

For larger lists, a genexpr can be faster because, I suppose, all the allocations needed for the listcomp start taking up more time

unkempt rock
peak spoke
grave jolt
#

makes sense

safe hedge
#

Is that linked to:

Which again... why I'm not sure. Perhaps since a list is definitely finite

peak spoke
#

That calls gen_send_ex2 which is a fairly big func, while the list iterator simply has to check if the index is valid and then fetches the list item

safe hedge
#

Which was my initial guess

grave jolt
#

well, yielding from a generator is really sending None to it, which involves some machinery

unkempt rock
#

What do you mean by sending None to it?

wide widget
#

is there a way to change just the name of a method in a python class during runtime..

grave jolt
#

x = next(generator) <=> x = generator.send(None)

#

what you send to a generator becomes the value of the yield expression

#

!e

def f():
    print((yield 1))
    print((yield 2))
    yield 3

g = f()
assert g.send(None) == 1
assert g.send(1234) == 2
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

1234
languid dagger
#

You only need to use .send(None) start your generator if it should be taking input x = yield

grave jolt
#

well, yes, you wouldn't actually call send with the literal None

#

but the effect is the same

#

.send can be used to make some fun contraptions

#

!e

def null(genfn):
    def fn(*args, **kwargs):
        gen = genfn(*args, **kwargs)
        accumulator = next(gen)
        while accumulator is not None:
            try:
                accumulator = gen.send(accumulator)
            except StopIteration as e:
                return e.value
        return None
    fn.gen = genfn
    return fn

@null
def read_from_config(config):
    foo = yield config.get("foo")
    bar = yield config.get("bar")
    baz = yield config.get("baz")
    return (foo, bar, baz)

print(read_from_config({"foo": 1, "bar": 2}))
print(read_from_config({"foo": 1, "bar": 2, "baz": 3 }))
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 | None
002 | (1, 2, 3)
safe hedge
#

Explain

brave badger
#

I see Maybe lemon_eyes

unkempt rock
#
In [1]: def f():
   ...:     print((yield 1), 2)
   ...:     print((yield 2))
   ...:     yield 3
   ...: 
   ...: g = f()
   ...: assert g.send(None) == 1
   ...: assert g.send(1234) == 2
1234 2

Not sure if I understand this either

safe hedge
#

Oh it took me way too long to realise why it printed None haha

unkempt rock
#

it would've made sense if the output was 2\n1234 to me, what does yield 1 becomes when you send None?

grave jolt
brave badger
#

You mean burritos? Anyways, the send/yield feedback loop is a bit hard to get hold of

fleet phoenix
#

Is there a way of printing files through python.

unkempt rock
#

"the current yield expression always evaluates to None." Passing None to print doesn't do the same thing though.

fleet phoenix
#

printing like real printing

mint forge
#

uh no

fleet phoenix
#

ok thanks

feral cedar
#

there probably is

fleet phoenix
#

yes i will research

undone hare
#

Yeah, there surely is

mint forge
#

did he not mean like actually print, a file like print it in paper?

fleet phoenix
#

yes

#

print a file in paper

mint forge
#

and python has that? anyways pydis_off_topeek

feral cedar
#

i mean, how do you think you tell your printer to print

#

it's probably possible

fleet phoenix
#

can someone help me find it??

sacred yew
#

are there are any uses for generator send() aside from coroutines?

#

because it seems like a strange feature to add to generators

#

but given that a lot of langs have it, there's probably something im missing

grave jolt
#

I don't know if it has 'normal' usages

#

!warn @ionic jetty Stop asking for help with passing an educational system.

fallen slateBOT
#

failmail :ok_hand: applied warning to @ionic jetty.

grave jolt
# sacred yew but given that a lot of langs have it, there's probably something im missing

This can be useful to implement a weird version of dependency inversion
Direct call:

def get_user(uid: int):
    return execute_sql("SELECT blah blah blah", (uid,))

dependency injection:

def get_user(uid: int, execute_sql: Callable[[str, Tuple[Any, ...]], Any]):
    return execute_sql("SELECT blah blah blah", (uid,))

using a generator:

def get_user(uid: int):
    rows = yield ExecuteSQL("SELECT blah blah blah", (uid,))
    return rows

or even better:

def get_user_by_uid(uid: int):
    rows = yield ExecuteSQL("SELECT blah blah blah", (uid,))
    if rows == []:
        return None
    [user_row] = rows
    return make_user_from_sql_row(user_row)

you could abstract these lower level requests with other generators:

def get_subordinates_of_user(user: UserMetadata, user_repo: UserRepo):
    results = []
    for uid in user.subordinate_uids: 
        subordinate = yield from user_repo.get_user_by_uid(uid)
        results.append(subortinate)
    return results

...which is not a great example because it makes N+1 requests, but you get the idea

so whatever you do with it, you end up with some kind of monad hyperlemon

#

not very useful, but kinda interesting.

deft pagoda
#

i used .send in my range implementation of __xor__, __or__, and __and__

swift imp
#

How the hell r u supposed to deal with cyclic imports when trying to do type hinting

peak spoke
#

stick imports under if typing.TYPE_CHECKING: ...

grave jolt
#

another option is -- unsurprisingly -- to not have circular imports 🙂

swift imp
grave jolt
#

What do you mean? What would go into that file?

swift imp
#

I see in there now @peak spoke advice

grave jolt
#

ah, well, yes, you can do that if some types are shared between modules

#

how many shared type aliases do you have?

swift imp
#

A dozen or so

#

Really I need to breakdown some core files probably

#

but whatever

mossy heron
#

For folks who have successfully packaged their python cli app as a standalone executable in Linux systems: What did you use? I'm trying out PyOxidizer but running into hiccups with their getting started 🤔

sacred yew
#

does t pyinstaller also work on linux

raven ridge
#

It does, though my experience is that it can be fiddly.

swift imp
#

Anyone ever work with annotations, descriptors and mypy and how much success have you had ?

crisp wedge
#

does anyone know how i can create a reset button (or a loop) for a pygame
i would greatly appreciate it
ping me if you do

mint forge
crisp wedge
#

oh thx

vivid pewter
#

hi
typescript has interfaces for type checking. and those interfaces dont get compiled.
is there anything similar we can use in python?

like in a rest api i can define interface which will make it easy to see what type of object (its keys etc.) is being returned

unkempt rock
#

python has their version of type hints and checks yea

#

heres a guide on it

flat gazelle
#

You have TypedDict for dicts, and just type hints for regular classes

vivid pewter
#

ah okay thanks @unkempt rock @flat gazelle
I'll check these out

desert peak
#

@vivid pewter however small, type hints in python have a runtime cost and are not stripped

undone hare
#

What would be this runtime cost?

feral cedar
#

a few nanoseconds probably, i suppose we should actually benchmark

zenith topaz
#

I wonder how much the difference is between the current and the __future__ implementation.

fleet phoenix
#

hey public santa void main a have another challenge if you want i can send u the ansewer but that would be cheating

peak spoke
#

The runtime cost shouldn't matter however big it is, as the definitions will only be ran once. And it'll get smaller after postponed evaluation becomes a thing by default

feral cedar
#

what

desert peak
feral cedar
#

wow, really?

fleet phoenix
#

yes

desert peak
#

Yeah, the maintainer has shared his views on various issues about the matter

zenith topaz
#

They could add type hints files

desert peak
#

It's in typeshed, but that's not really the same

feral cedar
#

i thought they were essentially just comments

desert peak
#

@fleet phoenix This is not a general channel. If you're not here to discuss the language, please find #python-discussion

zenith topaz
#

in the old system they are evaluated

brave badger
#

Not too sure how much casts impact performance although I might run into some problems if I start doing them a bit too much

fleet phoenix
#

yes sorry its just that general chat got silence

#

well not anymore buy

zenith topaz
#

it's a function call, that's the most of the overhead in cast I reckon

#

!e

class Test:
    @staticmethod
    def test() -> Test:
        return Test()

Test.test()```
fallen slateBOT
#

@zenith topaz :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 |   File "<string>", line 3, in Test
004 | NameError: name 'Test' is not defined
zenith topaz
#

!e

from __future__ import annotations

class Test:
    @staticmethod
    def test() -> Test:
        return Test()

Test.test()```
fallen slateBOT
#

@zenith topaz :warning: Your eval job has completed with return code 0.

[No output]
brave badger
#

cast-ing to actual types instead of string literals would produce LOAD_GLOBAL instead of LOAD_CONST guess I'll try benchmarking that

#

well that was to be expected I guess

In [3]: def one():
   ...:     cast(List, "12345")
   ...:

In [4]: def two():
   ...:     cast("List", "12345")
   ...:

In [5]: %timeit one()
183 ns ± 17.8 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit two()
163 ns ± 1.29 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
desert peak
#

wow

#

that is quite a cost

peak spoke
#

It's almost within the deviation, and tiny compared to even the function call overhead

desert peak
#

true, but it makes sense something like that would cause apprehension for a web framework developer to avoid

#

especially one as big as Flask

brave badger
#

Would it be possible for the parser to treat cast as a special case and strip it altogether?

peak spoke
#

You don't really use it that much with hinting

brave badger
#

I use it a bit too much in my lib

desert peak
#

I use pydantic which is entirely driven from type hinting lemon_sweat

brave badger
#

8 invocations in total but on critical functions; yeah I'm stripping that out lol

grave jolt
#

I don't think I ever needed to use cast

#

doesn't assert work as well?

#

or a directive like # type: ignore

vapid wharf
#

@tidal quiver

visual shadow
#

Wait, flask is adding type hints though i think isn't it?

#

I think the guy mentioned it in passing literally yesterday or day before.

red solar
#

That would be dope if true

boreal umbra
#

I learned recently that dunder methods can't be async. Do you think changing that for some number of dunder methods is in the backlog for the cpython devs?

peak spoke
#

What methods do you have in mind?

raven ridge
#

There's a new thread on python-ideas today proposing async constructors via a metaclass...

boreal umbra
boreal umbra
peak spoke
#

that would also need some alternate syntax, can't think a nice way now

boreal umbra
#

I suppose await thing[a] = b would break the parser

raven ridge
grave jolt
#

set: await thing[a, b]
get: await thing[a]
but that's... more on the cursed side of things

#

this brings a question of why thing[key] = value might be better than thing.set(key, value)

#

I've been doing a bit of JavaScript, and one thing that annoys me a bit is that some interfaces for doing essentially the same thing can be very different.

// iterate over [key, value]s of a map
for (const [k, v] of myMap)
    console.log({k, v});

// but in forEach it's [value, key]. WTF?
myMap.forEach((v, k) => console.log({k, v}));

so making a built-in mechanism for such actions (like a foreach loop) can make some interfaces automatically more familiar

peak spoke
#

That get would conflict with its current behaviour

boreal umbra
coarse jungle
#

yo

grave jolt
coarse jungle
#

someone teach me python

#

:)

boreal umbra
#

!resources @coarse jungle -- this is strictly a discussion channel though

fallen slateBOT
#
Resources

The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.

coarse jungle
#

hmm see I wanna learn it but do I want to do the work to learn it hmmmmm?

boreal umbra
#

jk 💚 💚 💚

grave jolt
#

no I'm not hyperlemon

coarse jungle
#

:) smile

coarse jungle
#

hmmmm I feel like some nerd will teach it to me and it will be fine

boreal umbra
coarse jungle
#

I feel like your wrong

#

:)

boreal umbra
grave jolt
#

it's not possible to learn something by just listening to "some nerd" (unless you believe in supernaturally acquired knowledge)

coarse jungle
#

see what I think is, hear me out. drugs, voicechat, friendships, and yea.

#

yea know

grave jolt
#

Anyway, this discussion does not belong here. Please move to off-topic.

coarse jungle
#

oop k

fresh cargo
#

Given that sets are unordered, how is the order of the elements determined when poped or printed?

#

I'm curious why this happens:

>>> {5, 6, 7, 8, 9}
{5, 6, 7, 8, 9}
>>> {6, 7, 8, 9}
{8, 9, 6, 7}
sacred yew
#

probably the order of the hashtable

fresh cargo
sacred yew
#

iirc hashtables start with a small table of size 8

#

so im guessing its hash mod 8

grave jolt
#

it can do whatever it wants to choose it

#

even random.choice, if you want to be silly

sacred yew
#

time to dig into the source

fresh cargo
grave jolt
#

well, maybe, but you probably shouldn't rely on it 🙂

raven ridge
spark magnet
#

@fresh cargo there is no guarantee about the order, so internal details will affect the order

sacred yew
#

The initial probe index is computed as hash mod the table size.

#

table size starts at 8

fresh cargo
spark magnet
#

yeah, i don't know what's going on in there

fresh cargo
#

Ah I start to understand a little

#

{5, 6, 7, 8, 9} has 5 elements

#

If I do {5, 6, 7, 8} it'll also become {8, 5, 6, 7} like the second one

#

I guess 5 elements increase the table size?

spark magnet
#

¯_(ツ)_/¯ 🙂

sacred yew
#

at 5 elements the table size increases to 32

#

and i have no idea where in the source this occurs

#
    if ((size_t)so->fill*5 < mask*3)
        return 0;
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);

looks like resizing occurs when the table is ~3/5 full

fresh cargo
#

So it multiplies by 4 each time when table size is small. Explains 8 ⇒ 32

sacred yew
#
    i = si->si_pos;
    assert(i>=0);
    entry = so->table;
    mask = so->mask;
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
        i++;
    si->si_pos = i+1;
    if (i > mask)
        goto fail;
    si->len--;
    key = entry[i].key;

this is setiter_iternext

#

looks like linear traversal order through the entire hashtable

spark magnet
#

the one implementation detail I used for a talk was showing how to make sets have pathological performance by using poorly chosen ints as elements

unkempt rock
#

Really general implementation question

#

I have a python script that takes in a video file and returns text

#

I have this script on a VPS

#

how can I send this file to the VPS and process it with the python file then return the text

#

from like an app

#

like how should I host the python server so that it can recieve videos?

sacred yew
#

http?

#

also this would be more suited for a help channel

#

@unkempt rock

faint lion
#

one of my (current) favorite yet simple feature are tuples which are effectively read-only list which can be useful for data being sent that really shouldn't be modified like a cookie and if you want you technically can write to them but it is round about way (at least how i would do it which is a conversion to a normal list and run operations on that then make it back into a tuple)

peak ore
#

Hey, I’m new but I was wondering if anyone could help me out with a problem. Is this the right chat for that?

sacred yew
#

this is more for meta-discussion about python itself

peak ore
#

Okay cool. Thanks

fresh cargo
#

Is there a reason to use dict.keys() other than readability and symmetry with dict.values() and dict.items()?

smoky turret
#

dict.keys() is setlike, so you could do set stuff on the keys directly

#

though thats not particularly common

brave badger
#

Most of the time you can just use the dict directly anyways

fresh cargo
smoky turret
#

of course, but I'd imagine its slightly slower

#

either way, I was just answering the question

fresh cargo
#

Just curious 😛 Thanks to you both

smoky turret
#

actually, I recall doing some quick and dirty testing awhile ago, and I recall dict.keys() requiring constant time for creation since I think its basically just a memview with a set wrapper

#

havent done extensive testing though

fresh cargo
#

Apparently it is faster

#
>>> timeit("set(x)", setup="x = {n:n for n in range(100)}")
2.1138495000000006
>>> timeit("x.keys()", setup="x = {n:n for n in range(100)}")
0.06084189999999978
#

Much faster

smoky turret
#

yeah, Im guessing its O(1) behavior vs O(nlogn)

paper echo
#

keys is just a view

#

set has to iterate and re-hash again

#

Try list(x) vs list(x.keys())

#

I doubt it will be anything more than a tiny difference

#

I use .keys too for visual clarity

unkempt rock
#
In [1]: d = dict(zip(range(20000), range(40000, 60000)))

In [2]: %timeit list(d)
210 µs ± 10 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [3]: %timeit list(d.keys())
213 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Makes sense

unkempt rock
#

Hello folks. I am iterating nested lists and wondering how to improve performance. I am actually loading a matrix of pixels (r, g, b) from a PNG:

#
    image_matrix = images.load(image_filename)
    rectangles_pixels = {}

    matrix_width = len(image_matrix[0])
    keep_searching = True
    while keep_searching:
        for y in range(len(image_matrix)):
            keep_searching = not rectangles_pixels
            for x in range(matrix_width):
                if image_matrix[y][x] > (0, 0, 0):
                    rectangles_pixels.setdefault(image_matrix[y][x], []).append((x, y))
                    keep_searching = True
#

The "if" check, performed on each column of almost every row is incredibly expensive. The "while" loop above represents about 99% of my total execution time.

#

This is what kernprof reports:

#

(the numbers on the left represent the % of time spent on each line)

#

What can I try to speed up the loop? I doubt a conversion to bytes would help. I tried with "is" comparisons rather ">" for the black tuple.

#

Would the iteration of a precomputed list(range(matrix_width)) be faster than the repeated call to "range"?

brave badger
#

@unkempt rock For future reference, this isn't really the appropriate channel for that type of questions, a help channel would definitely be better, but to address your question: the report seems a bit erroneous, the for loop itself, not the code it has in the block, shouldn't have much overhead. If you're dealing with matrices then I suggest numpy as you should be able to perform operations against those given the appropriate set up.

unkempt rock
#

@brave badger I agree, the report looks suspicious. The 0.0% in the "y" for loop above all else. I am limited to the built-ins, so I can't use a better PNG library (that returns a handier object) or numpy. Thanks though.

brave badger
rigid forge
#

im just learning how to use python

little tusk
#

Hello

#

I have a few questions and sorry if wrong chanel

#

anybody care to help?

undone hare
little tusk
#

ty

boreal umbra
#

@rugged nexus if you wanted to talk about Discord itself, that might be a topic for one of the three off-topic channels.

unkempt rock
#

I am trying to replace a for loop generator:

#
def generate_perimeter(topleft_coord, bottomright_coord):
    xmin, ymin = topleft_coord
    xmax, ymax = bottomright_coord
    for i in range(xmin, xmax + 1):
        yield i, ymin
#

Ideally I would like something like this, which obviously won't work though:

#
yield from zip(range(xmin, xmax + 1), constant(ymin))
#

Because zip isn't a generator but an iterator.

#

constant is itself a generator of the form: def constant(x): yield x ... a bit redundant.

grave jolt
#

In the future, use our help system (see #❓|how-to-get-help) to get help. This is a channel for meta-discussions about Python

unkempt rock
#

Alright, sorry @grave jolt.

#

(can't use itertools.repeat due to requirements, good night!)

grave jolt
unkempt rock
#

As far as I understand itertools.repeat(1) is the same as def repeat(): yield 1

#

That's what I am using as constant(ymin).

sacred yew
#

with a while True

#

otherwise it only yields once and then returns

#

@unkempt rock

unkempt rock
#

@sacred yew You're right. The first yield will exhaust the generator.

red solar
#

Anyone been following the move discussion on python ideas mailing list?

#

Trying to understand how they want this to apply to python (I get how it works in c++)

pliant tusk
#

@red solar link?

red solar
#

Hmm one sec

golden imp
#

I have a weird sys.path question.
I am debugging code on two different machines, and the python installation in one seems to have an odd behavior that is adding the absolute path from where the python interpreter is called to the sys.path

#

Is there some installation-specific setting that causes this?

pliant tusk
#

@red solar found it

red solar
#

oh lol

#

@golden imp the only thing i can think of is the checkbox when you install python asking if you want to add it to your path....

indigo yarrow
#

This looks like lifetimes!

golden imp
#

@red solar nah that's not it, it changes as I start the interpreter from different directories

red solar
#

i mean in the loosest sense maybe? lifetimes is a lot more than just this tho

#

oh

#

you're starting the interpreter with the same command in all cases right? are they the same OS and python that you're running installed in the same location?

golden imp
#

different OSes, and slightly different python versions unfortunately (3.7.7 vs 3.7.9), so not a direct comparison

pliant tusk
#

@red solar seems like it would just give typehinters a concept of ownership over a variable

indigo yarrow
#

You're right, but move here seems to be serving a very similar purpose. They just look really similar :D

#

ah, smarter people than I have made comments about this in the thread. *poof*

red solar
#

Lol u can still discuss it just cuz smarter people already discussed it

indigo yarrow
#

nothing to add :)

red solar
#

Sh33mp gimme a sec to try it out on my windows+Linux

golden imp
#

it's centos vs ubuntu

red solar
#

ah :/ then i'm even more surprised think1

#
def f(d: Move[dict]) -> dict:
    d['a'] = 2
    return d

d = {1: 2}
f(d)
print(d[1])  # mistake, using of moved value
#

oh wait there's so many more comments on the actual thread

indigo yarrow
#

yee

red solar
#

wow this is so much better than following it through email

indigo yarrow
#

ah, man, if you have one of the tree-threaded clients it makes it easier to follow, too

red solar
#

do u suggest one for ios? my pc situation is a bit iffy rn so i don't tend to access email on pc atm

indigo yarrow
#

No I do not. I don't know of any on mobile :(

red solar
#

@golden imp which version of ubuntu and centos?

#

damn :/

#

actually... wait which one are you getting paths that aren't absolute?

#

cuz both on win10 and ubuntu20.04 i get absolute paths

golden imp
#

oh weird, I got it

red solar
#

What was it?

golden imp
#

it comes down to the PYTHONPATH. if it ends with a : it adds the absolute current directory I guess

#

interesting

#

(if it's empty it doesn't add it)

red solar
#

If u have time, can u make a stackoverflow post about it and then answer it?

#

Seems like something obscure that would help other ppl too

golden imp
#

can you do that? add a question and answer it yourself

red solar
#

Sure

#

It’s even encouraged

golden imp
#

unfortunately when I was searching this didn't come up

#

thanks anyway!

red solar
#

hmm didn't appear for me either - glad you found it tho 🙂

hearty trench
#

anyone have resources to get better at solving algorithm problems

paper echo
#

@indigo yarrow what is a 3 headed client

indigo yarrow
#

@paper echo lol. Medusa, release v3.3

paper echo
#

Ive never heard of medusa

#

It's a mailing list reader/client?

indigo yarrow
#

It is not real. It was an attempt at humor based on your misunderstanding.

brave badger
#

Apparently, you can pass 1 and 2 to open and have it return a handler for stdout and stderr respectively

#

!e

import sys
import io
sys.stdout = io.StringIO()
sys.stderr = io.StringIO()
open(1, "w").write("hello")
open(2, "w").write("world")
sys.stdout.seek(0)
sys.stderr.seek(0)
print(sys.stdout.read())
print(sys.stderr.read()) 
fallen slateBOT
#

@brave badger :white_check_mark: Your eval job has completed with return code 0.

helloworld
brave badger
#

@north root @low lagoon See this

low lagoon
#

what in fresh hell

#

that's actually pretty neat

brave badger
#

I assume it's a leftover feature from the old days

gleaming rover
#

what I'm more interested in is

sacred yew
#

this isn't a help channel

gilded jungle
#

Oh mb I was in ahelp channel and they told me to come here

brave badger
gilded jungle
#

Alright thank you!

brave badger
north root
#

interesting

#

apparently it breaks stdin or something in the repl?

>>> open(True, 'wb').write(b'Hi\n')
Hi
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 9] Bad file descriptor
>>> exit()
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
OSError: [Errno 9] Bad file descriptor
#

or it breaks both stdin/out somehow lol

#

not sure

raven ridge
#

that's probably just something trying to close stdout twice.

#

try:

open(True, 'wb', closefd=False).write(b'Hi\n')
north root
#

ah yeah, that works

#

it doesn't error if i use a context manager

raven ridge
#

now, though, note that file descriptor 1 is probably stdout, and 2 is probably stderr, but that's not guaranteed, and can be changed while the process is still running.

north root
#
>>> with open(True, 'wb') as f:
...     f.write(b'hello\n')
... 
5
hello
>>> exit()
raven ridge
#

e.g., you can close fd 1 and open something new, and the new thing you open will be the new fd 1, and passing True to open the next time around will create a wrapper around that file instead of stdout

sacred yew
#

isn't stdout defined to be 1

#

same with stdin/stderr

raven ridge
#

well: when a program starts up, there's no guarantee that file descriptor 1 or 2 are open.

sacred yew
#

so?

spice pecan
#

The question is, does it pull them from sys.stdout/stdin/stderr or is it capable of opening them?

sacred yew
#

that doesn't mean 1/2 aren't stdout/err

#

it just means that stdout/err are closed

raven ridge
#

well, as far as 1/2 are concerned, that probably depends a lot on OS.

sacred yew
#

oh yeah this is probably unix-specific

raven ridge
#

technically I think the only guarantee you get is that the default stdout is STDOUT_FILENO, I think

#

and likewise with STDERR_FILENO

sacred yew
#

isn't that defined as 1?

#

yeah it is

raven ridge
#

sure, but that's just POSIX

#

other OS's exist

sacred yew
#

other os's dont have stdout_fileno

raven ridge
#

hm, I thought C gave it, not POSIX, but you're right

#

C doesn't even seem to guarantee the existence of file descriptors, so - given that, using the numbers is very clearly not portable, heh

sacred yew
#

more implementation specific:

#
>>> x=open("asdf","w")
>>> open(3,"w").write("Hello")
5
>>> y=open("asdf","r")
>>> open(3,"r").read()
'Hello'
raven ridge
#

it's not implementation specific - the language requires this to work, it's not just CPython

#

but it's not portable in the sense that there's no portable meaning to any particular file descriptor - you can't portably assume that 1 is stdout and 2 is stderr, unless you're limiting yourself to POSIX

raven ridge
raven ridge
shrewd dune
#

@north root I wasn't paying attention. I suppose the reason it does't work in the REPL is because of the garbage collector (even if you disable it, for whatever reason)

#

because instead of writing it like that you could do```python

f = open(1, 'w')
f.write('hello')
5
f.flush()
hello>>>```

#

but I'm not 100% sure lol

#

in any case, you could run it without the REPLshell $ python -c "open(1, 'w').write('hihi')" hihi

#

oh, it's probably related to the number of written bytes returned by write and the REPL trying to echo it actually, not really

#

and something about the implementation

#

No idea

#

if you don't like errors, you could always close stderr```python

import sys
sys.stderr.close()

1 / 0
gg

grave jolt
#

lmao

#

it's like when someone refuses to listen to your arguments

#

just cover your ears.

shrewd dune
#

were you who tried to do ~await x?

grave jolt
#

yes

#

still in great misery...

shrewd dune
#

this was months ago and I never told you...

#

it doesn't say why, but they said it's not valid

grave jolt
#

!e

async def f():
    -await x
fallen slateBOT
#

@grave jolt :warning: Your eval job has completed with return code 0.

[No output]
grave jolt
#

but - is fine?!

#

wait, no, I did a different thing

#

I did await ~x

#

!e

async def f():
    await ~x
fallen slateBOT
#

@grave jolt :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 2
002 |     await ~x
003 |           ^
004 | SyntaxError: invalid syntax
grave jolt
#

yep

shrewd dune
grave jolt
#

!e

async def f():
    await -x
fallen slateBOT
#

@grave jolt :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 2
002 |     await -x
003 |           ^
004 | SyntaxError: invalid syntax
grave jolt
#

alright, I could've just done await x xD

#

the whole project was an... "exploration"

#

I was replicating the IO monad from Haskell

shrewd dune
#

btw, related to the previous conversation, you could always get the proper file descriptor from sys.stdout.fileno(), but it was a joke snippet

sudden tusk
#

Hello, anyone here moderately experienced in pyQt?

gleaming rover
sudden tusk
#

thanks

shrewd hornet
#

who founded this discord server? Was it @fossil pumice?

mint forge
#

@shrewd hornet a question more suited to #community-meta, ( not it was not lemon, it was some guy named jhon but he gave the ownership to @joe#6000 )

sly junco
#

Heyo, so I have a more of a "what're your thoughts" sort of question.

What do y'all feel about global objects instantiated at the bottom of modules for use in libraries?

#

Example:

# module.py

class MyObject():
    # ...


global_object = MyObject()```
#

and then accessing like from module import global_object

brave badger
#

In terms of specialized use-cases like singleton objects, that's a perfectly acceptable pattern to use, it requires less effort but provides nearly the same functionality as a a class that hijacks __new__.

sly junco
#

The goal is to use descriptors to perform some logic when instance attributes are accessed, but to obfuscate this so it seems like, from the user's perspective, you are just accessing module level-attributes. like global_object.my_attribute

#

I don't hate this pattern, I've seen it used many times, I just didn't know if this was considered bad python style

narrow kettle
#

hmm thoughts on allowing syntax like this, ```py
async def foo():
session = async with aiohttp.ClientSession()
resp = async with session.get('someurl')
[scope block using the resources that need to be closed]
#end of scope, with block objects are closed

radiant fulcrum
#

inst that like the entire point of a context manager

narrow kettle
#

ehh, the main benefit of this is it reduces nesting

#

afaik contexmanagers still need a with block

#
using(var client = HttpClientFactor.GetClient())
{

}
vs

using var client = HttpClientFactor.GetClient();
#

i dont use using blocks AT ALL anymore and my code looks way cleaner as a result

#

theres no imo reason to have dispose blocks be in a new "scope"

sly junco
#

Someone else please correct me, but if you wanted to combine context managers, I'd recommend creating your own context manager object, wrapping their __enter__ and __exit__ methods within your own. You can also take a look at the contextlib library to help out, specifically AsyncExitStack

spice pecan
#

You can already use multiple objects in a single with though IIRC

#

Not sure about async with

narrow kettle
#

it still requires a new scope block

#

and mulitple in one is also super hard to parse at first glance

#

there are many ways to do it but none of them really solve the key issue in a nice way

spice pecan
#

Frankly I'm fine with something along the lines of

with (open('file1.txt') as file1,
      open('file2.txt') as file2):
    do_stuff()

Though I do understand your point about scopes

peak spoke
#

Don't think I've ever had a problem with the indentation a with block introduces

narrow kettle
#

its just unecessary, a new scope block implies some kind of control flow action within that block, an if, a for, a local function etc

#

a with block is none of those thigns

#

so parsing it mentally becomes a quick backtrack because you see a new scope and you think "something regarding this codes flow happens here"

#

but it doesnt, its just a dispose, theres no need for you to even think about that

narrow kettle
#

its what i do for multiple files

spice pecan
#

Didn't test the parens, but in a single line yeah, it works

undone hare
#

cool

narrow kettle
#

im not sure if it works for things like this tho

peak spoke
#

It should in 3.9

spice pecan
#

I remember a mailing list submission for implicit line continuation in such cases

narrow kettle
#
        async with aiohttp.ClientSession() as session:
            async with await session.get(url="/") as resp:
#

idk if you can reference session inline in the same with

peak spoke
#

the old parser will fail with it and needs the backslash continuation

narrow kettle
#

but ya the with pattern im proposing would help tremendously with the async with pattern

#

then dispose order is from the bottom up as it always is with with

spice pecan
#

It does seem to support referencing inline

#

!e ```py

class Sample:
... def enter(self, *args):
... return self
... def exit(*args):
... pass
... def init(self):
... self.other = self
...
with Sample() as first, first.other as second:
... print(second)
...
<main.Sample object at 0x000001943B6B8550>```

fallen slateBOT
#

@spice pecan :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 |     >>> class Sample:
003 |     ^
004 | SyntaxError: invalid syntax
spice pecan
#

oh right

narrow kettle
#

does that work for async with

spice pecan
#

you see the point

quiet nebula
#

i need some help with base64 in python

spice pecan
#

not sure about async

narrow kettle
#

what if you had async with and a regular with

#

theres alot of cases where the inline jsut falls short, and it also still requires at least 1 new indent and its harder to parse at first

#

i also already gave you an example of base64

quiet nebula
#

@narrow kettle im new in discord too, i needed help and i join here, sry bro

spice pecan
#

I personally don't agree, but I wouldn't mind having that either

peak spoke
#

To me it feels like it'd encourage to keep resources open unnecessarily long

spice pecan
#

^

narrow kettle
peak spoke
#

You can be doing something long running within them, during which time a file handle could be left open for example, possibly blocking other accesses and leaving it prone to corruption

narrow kettle
#

im not following

spice pecan
#

I've never encountered a case where I'd need to nest async with and with enough for it to become a problem, and I really like the explicit nature of an indented with block - it clearly establishes that some sort of resource is acquired, worked on and then released as soon as it's not needed

narrow kettle
#

how does a statement make that more likely then a block

#

i can say from experience that this feature was a god send in c#, its been so nice to not have to create new scopes everywhere

spice pecan
#

C# is a bit of a different story though, I prefer the using statement there as well

#

In Python, I'd stick with an indented with

narrow kettle
#

perhaps i just have a thing against indentation

#

i keep my flow as flat as possible at all times

#

keeps things way easier to read imo

spice pecan
#

I try to flatten the code wherever possible, but a with block never really felt problematic to me in that regard

narrow kettle
#

i have a fair amount of async with requests with aiohttp

#

the "pyramids" have alwasy bothered me

odd ether
#

@unkempt rock excuse me?

#

!warn 539398639999516677 I don't know what made you say that, but throwing insults in random channels won't be tolerated.

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied warning to @unkempt rock.

sacred yew
#

@narrow kettle no, creating a new indent level is good

narrow kettle
#

Excuse me

sacred yew
#

helps clearlybshow where the scope ends

#

"explicit is better than implicit"

narrow kettle
#

In this case it’s not being explicit, it’s a break from other behaviors

sacred yew
#

wdym

narrow kettle
#

Indents in python imply control flow

#

Obviously it’s not real scope

#

But the indent says “this section has flow implications”

#

A with block does not do that

sacred yew
#

ok it kindof is overloading the concept of indentation

narrow kettle
#

The general usage of a with block that I’ve seen basically are just wrapping the entire contents of a function in the with

sacred yew
#

But it is much better than just a statement

narrow kettle
#

That’s a needless level of indent

sacred yew
#

then those functions are poorly written

narrow kettle
#

?

#

No they are good

#

Small methods

#

Narrow scope

sacred yew
#

ok that's fine

narrow kettle
#

That’s what you want

#

The with indent is redundant

#

Scope already ends when the function exits

#

It gets worse with nested with blocks

#

Suddenly you are creating 2 sometimes 3 levels of indent on top of the class and function scope

#

Totally unneeded

sacred yew
#

this pattern seems to encourage leaving resources open for the entirety of a function

narrow kettle
#

That’s already what happens

sacred yew
#

just like it would be without context managers

narrow kettle
#

Ideal a function should end WHEN the resource is closed

#

Like that’s how you should write it

#

With blocks have a place oc, esp in python with top level scripts etc

#

And lord knows the amount of shitty py code is written all in top level in one module

#

But for larger projects, with a more oop focus and all classes it becomes more valuable

sacred yew
#

this still seems like it would encourage bad practices

#

since its only really good if you use small functions

#

and thats a big if

narrow kettle
#

We are all adults here is what quido says

#

There is TONS in python that encourage bad habits

#

It’s very open

sacred yew
#

like what

narrow kettle
#

But it allows you to express CORRECT patterns in a much simpler way

narrow kettle
#

Access control doesn’t exist, reflection is as easy as one or two calls

sacred yew
#

it seems more complex to me

narrow kettle
#

Monkey patching is a thing

#

Dynamic method attributes

sacred yew
#

ok

#

but in those cases

#

unsafe code looks unsafe

narrow kettle
#

All these things encourage shitty code while also allowing for idiomatic expressions in different cases

sacred yew
#

if you see monkeypatching , then you know "oh this code is unsafe"

#

for yours

#

the only indicator that its safe is one "with" expr at the top a function

#

since otherwise it looks exactly the same as no context managers

narrow kettle
#

But you really don’t CARE about constantly knowing it’s safe with statements allow you to use it as a normal variable and forget about it, you can keep a resource open for too long in a with block as well

#

Coming from a langauge that does have this it’s an amazing feature

sacred yew
#

with blocks are supposed to make it easy for you to manage scope

narrow kettle
#

You aren’t managing scope persay you are managing lifecycle

#

And more often then not lifecycle lines up with scope

#

And if it’s not then that’s often times code smell

#

Your methods are doing too much

#

Break it up

#

In my mind having a function with a with block that would have adverse effects if you made the entire function within the with blocks scope is major smell

sacred yew
#

perhaps

#

but that still doesn't justify your solution

narrow kettle
#

Def foo()
with some thin:
Code

     Code

As opposed to

Def foo()
foo = with something
Code

Code
#

Sry about formatting im@on my phone

#

But ya those two things are the same

#

And if you have a method that doing the second too would cause adverse effects that’s not a sign a with statement is bad

#

It’s a sign you wrote bad code

sacred yew
#

compare

narrow kettle
#

I didn’t come up with this

sacred yew
#
def f(x):
  x = open("some_file.txt")
  for l in x:
    print(l)
    #do other stuff

with

def f(x):
  x = with open("some_file.txt")
  for l in x:
    print(l)
    #do other stuff
#

any other langs that implement this other than c#?

#

also c# appears to overload using with 2 different uses

#

so its not exactly the best comparision for good language design

spice pecan
#

there's more actually

sacred yew
#

correction

#

4 different uses

spice pecan
#

most of them came as C++ legacy IIRC, but yeah

narrow kettle
#

I probably woulda made the import syntax different but there’s a lot of backwards compat there

#

The c# team knows it, nothing they can do now

sacred yew
#

and c++ isn't exactly a well designed language

narrow kettle
#

Modern c++ is pretty nice

sacred yew
#

too much legacy c stuff

narrow kettle
#

But as someone who writes a lot of c# in practice using isn’t really a confusing distinction

#

C#s more enterprise tooling generally handles imports for you automagically

#

So you only write a using for resource consumption

narrow kettle
sacred yew
#

both snippets look very similar

#

except one is safe

#

and the other is unsafe

narrow kettle
#

I mean it’s a while ass keyword

#

That’s not that hard to differentiate

#

And it’s certainly not as much of a mental load as parsing nested withs which both create new indents AND flip the lhs and rhs semantics of variable assignment

sacred yew
#

imports also flip lhs and rhs

#

and the new indents are good

#

because it clearly shows that its within a with block

narrow kettle
sacred yew
#

i dont quite see how one level of indent creates more mental load

narrow kettle
#

One isn’t necessarily bad, it’s when they are nested that it gets bad

spice pecan
#

I wouldn't call new indents mentally heavy, if anything they help see where the resource is acquired and where it is released

sacred yew
#

^

spice pecan
#

Though yeah, nesting can be an issue ig

narrow kettle
#

In practice, for the majority of operations you don’t NEED to know exactly when it is released

sacred yew
#

uhhh

narrow kettle
#

Having an open file for a few extra micro seconds while the function ends is not bad at all

sacred yew
#

see

#

the reason why with blocks even exis

narrow kettle
#

If you NEED a fine grained control then you probably want the with block or even a try finally

sacred yew
#

is so you know exactly when it is released

#

and that applies to all resource managment

narrow kettle
#

It also exists so you write the resource once and don’t have to remeber to close it

#

Which IS a common thing

#

Write once, don’t worry

#

Which both a block and statement solve, and tbh a statement is faster to write anyways

sacred yew
#

yes

#

but with statmenets don't make it clear when the resource is released

narrow kettle
#

But the point remains, keeping a resource open for slightly longer then you need it is not necessarily bad

sacred yew
#

which is bad

sacred yew
#

its not explicit

narrow kettle
#

It’s just as explicit as a white block

spice pecan
#

It happens at the end of the scope, but python and C# handle scopes differently

narrow kettle
#

“When indentation ends”

sacred yew
#

and with resource managment, its really better if releasing resources is explicit

narrow kettle
#

Or sry scope

#

Which is the end of the function

spice pecan
#
if condition:
    x = with resource
do_stuff(x)

should that work, for example?

narrow kettle
narrow kettle
#

Tho that is up for discussion for sure

#

It could go both ways

spice pecan
#

For the sake of consistency with python, it should work

narrow kettle
#

I generally agree

spice pecan
#

but in, say, C#, ifs and flow control statements alike precede a new scope

narrow kettle
#

Yee, i def see the differences

#

It’s not 1:1 for sure

sacred yew
#

python doesn't have block scoping unlike c#

narrow kettle
#

Well i mean it has function scoping

narrow kettle
#

Which is similar and in practice often the same thing

narrow kettle
sacred yew
#

block scoping is very different from function scoping

sacred yew
#

great way to leak resources

narrow kettle
#

I’m saying well written python has functions that are chunked up into scopes that fairly closely mimic block scope

sacred yew
#

key word is "well written"

narrow kettle
#

I’m saying it’s not important to have fine tuned control of it when the difference is mostly just a few lines

sacred yew
#

well if you don't care when your resources are released, it's basically the same thing

narrow kettle
#

That’s picosecodns of difference

narrow kettle
#

That isn’t important

#

As long as it’s released nearish to where it’s not needed

#

Trust me i know about leaked resources, i actually had a prod instance crash last week due to a file descriptor leak

#

That one was fun, i just rebooted the entire docker deamon

#

But my point is in the vast majority of cases, the slightly more precise resource release a with block gives you makes no practical difference whatsoever

#

Most functions are “with block to get soemthing” then 4-10 lines that do soemthing simple with that result

narrow kettle
#

Which is what this allows you to write for

#

Many things CAN be abused for sure

#

But this allows people who are a bit more say experienced to flatten their flow while retaining safety

sacred yew
spice pecan
#

I wouldn't mind having a with statement, but I don't think it's too likely we'll get one. Besides the fact that the benefits of having it hardly justify the addition in most cases, it also makes it easier for beginners to do the wrong thing

sacred yew
#

it seems too easy to abuse

narrow kettle
#

Everything in python is easily abused

#

That’s part of what makes it so fun and dynamic

sacred yew
#

like monkey patching can be abused

#

but you don't see any beginners going around abusing it

narrow kettle
#

Dynamic attribute addition can be abused

#

Beginners are writing code that would be effected by leaving a resource open slightly to li mg

#

Long

#

There’s no practical difference to a beginner between a statement and a block

#

If anything they are MORE likely to use a statemnt due to its familar assignment semantics

#

The with block looks intimidating in

#

Ik that because I’ve tutored people that have been like 😳 when they read the docs

#

Because it flips assignment semantics

#

The use by statemnt is pretty clear

#

“This keyword means the language will make sure this variable is discarded properly”

#

Don’t think about it past that

#

And before the await syntax you might have said that the using after the = was unpythonic

#

But now there’s def precedent for a keyword that defines how a call is handled

sacred yew
#

using statement affects the entire function

#

await only affects 1 line

sacred yew
narrow kettle
#

To a beginner that’s all they need

#

You don’t need to describe external resources management etc

#

They just want to open a file

#

If anything you’ll see MORE beginners using with due to the simplistic nature of it

sacred yew
#

seems to me like encouraging bad practices of not caring about resource lifetimes

#

and it's bad that it's simple

narrow kettle
#

oop had to step away for a second,

narrow kettle
lusty schooner
#

I think it all depends on what you are doing with your code, how much optimization you want/need, etc. Also I don't think its a bad idea to implement best practices where you can.

narrow kettle
#

theres no practical difference between a function like this ```py
def foo():
with open() as f:
readlines

do a few things with the lines

and this py
def foo():
f = with open()
readlies
do a few things

#

these two methods will not have any practical difference in 99.999% of scenarios

lusty schooner
#

I don't disagree

#

As I said, there are times where it can be important though

narrow kettle
#

and if you are somehow DOING long running single threaded work in that one function then that work SHOULDNT be in that function

narrow kettle
#

im just offering a simpler use case scenario for something i run into alot

lusty schooner
#

I'm just typically annoyed myself by not closing out the resource lol

narrow kettle
#

and a feature that i USE all the time in other langs

lusty schooner
#

like OCD or something

narrow kettle
#

then youll probably be more likely to close out the resource if its just the addition of one keyword

lusty schooner
#

Yeah I mean with something that small closing vs closing when the program terminates is negligable

narrow kettle
#

with open() as f:
pass
vs

f = with open()

lusty schooner
#

right, so I use with so I know it is closed when finished

narrow kettle
lusty schooner
#

that was my point

narrow kettle
#

so the beginner/script arguement kinda loses some validity there

#

this isnt something for that usecase

lusty schooner
#

I'm assuming you are referring to the other's arguments of beginners and bad practices?

#

Yeah I think there are more important topics to be focused on for a beginner but it doesn't hurt to explain the difference I would say

narrow kettle
#

i currently have this all over some of my programs ```py
async def foo(self):
async with aiohttp.ClientSession() as session:
async with await session.get(url='url') as resp:
if(resp.status == 200):
pass #do some stuff

    function ends
#

that is a DEEP pyramid structure

#

changing it to this would be amazing

#
async def foo():
    session = async with aiohttp.ClientSession():
    resp = async with await session.get(url='url')

    if(resp.status == 200):
        pass #do some stuff
#

its a more linear structure and the variables session and resp are clear what they are becuase they follow typical assignment principles (lhs = rhs)

#

i gain nothing there from having 5 layers of indentation

lusty schooner
#

Yeah true

#

much more efficient and appealing if you could do the latter

narrow kettle
#

but imo its something iwth very few drawbacks and a high upside

#

python already has a really bad habit of becoming a "sideways pyramid"

sacred yew
#

the solution to a "sideways pyramid" isn't to change with to a statmenet

#

its to refactor your code

#

and your example isn't even bad

#

its just like goto

#

sure, it can make it easier to write code

#

but it hurts readability/debugging in the long run

sacred yew
#

the point is that one makes it clear where the scope begins/ends

#

and the other doesn't

narrow kettle
narrow kettle
#

its the same clarity as you know where the variables scope ends

sacred yew
narrow kettle
#

people dont say python should have { } because the scope of the variables is unclear

#

its very clear to people where that variables scope ends

#

adding a with doesnt change that

sacred yew
#

yeah because scoping is shown via indents

narrow kettle
#

not necessarily

sacred yew
#

which substitute for the braces

#

wait no

#

that doesn't even work xd

narrow kettle
#

you switched it

sacred yew
#

python doesn't have block scope

narrow kettle
#

the with block is a BREAK from traditional python

sacred yew
#

no it s not

narrow kettle
#

its not normal behavior

sacred yew
#

why not?

narrow kettle
#

python scopes end at the end of the function

#

the with block changes that

sacred yew
#

i mean you can access the with block's var after the function

narrow kettle
#

which is why it has diff assignement semantics

sacred yew
#

also

#

except clause scope changes too

narrow kettle
#

im not arguing against the with block

#

it has its use case

#

a with statement doesnt take mean the with block doesnt have some uses

#

it just makes the common redundant uses of the with not needed

sacred yew
#

its not redundant

narrow kettle
#

many uses of it def are

#

like my example for instance

#

the indents are 100% redundant and server no purpose

#

there is no reason they should be there

sacred yew
#

the indent helps you clearly know what the lifetime of the variable is

narrow kettle
#

not in this case

sacred yew
#

yes it does

narrow kettle
#

its the same

flat gazelle
#

lifetime until the function ends is pretty indicative

narrow kettle
#

its easy to know the lifetime the same way you know the lifetime of any other variable

#
def foo():
  x = 3




  function end
#

do you wonder when x goes out of scope?

#

i hope not lol 😁

#

why does adding a with to that make it unclear

sacred yew
#

because

#

x = open("file.txt")

narrow kettle
#

my point about the with block was that the vast majority of python scope is done at the function level

#

its the standard pattern

sacred yew
#

whats the lifetime of that

narrow kettle
#

this is merely an extension of that

#

i mean its lifetime is whatever you choose it to be

#

its open ended

#

not really relevant ehre tho

sacred yew
#

hmm ok

#

i still think the syntax is a little weird

#

and prone to mistakes

narrow kettle
#

you keep saying the with statement is unclear, but its quite literally the standard way to read python

sacred yew
#

no like

narrow kettle
#

i mean the syntax it self is changeable

sacred yew
#

its too easy to miss the fact that this variable has auto-closing

lusty schooner
#

^

sacred yew
#

and its weird that an expression affects the entire function's behavior

narrow kettle
#

elaborate

narrow kettle
#

like not at all thats a non issue

sacred yew
#

ok what would be the behavior of print((with open("file.txt")).read())

narrow kettle
#

i mean i said a with STATEMENT not a with expression

sacred yew
#

hol up

narrow kettle
#

so really the syntax would be ```py
x with = open()

#

like i said the syntax itself is up for debate

#

its just syntax, hardly the imporant part

gleaming rover
#

(minor point)

narrow kettle
#

well two more then my proposal

#
async def foo():
    session = async with aiohttp.ClientSession():
    resp = async with await session.get(url='url')

    if(resp.status == 200):
        pass #do some stuff

or

async def foo():
    session async with = aiohttp.ClientSession():
    resp async with await = session.get(url='url')

    if(resp.status == 200):
        pass #do some stuff
#

many possible syntax options

gleaming rover
#
async with ClientSession() as session, await session.get(url) as response:
    if (response.status) == 200:
        pass

not really sure if it's worth it

narrow kettle
#

yee that is a a thing, but at the same time, like thats def not somethign you want to be reading

#

like yes that exists, but its objectively a worse option then probably both the tohers

gleaming rover
narrow kettle
#

you prefer that over the double with?

somber halo
#

This question is not strictly related to Python itself but has anyone ever actually felt a need to implement some specific routines in C to do some intensive CPU bound work (to be called through Python of course) which weren't actually available by your typical packages for that purpose like numpy, numba and others?

#

I was reflecting a bit on this now and I've never actually felt that pain point so far I think

narrow kettle
flat gazelle
#

I wanted to do some image compression with custom algos which numpy didn't seem to have a way for. Numba should work the vast majority of things

somber halo
#

🤦‍♂️ That channel didn't occur to me.

#

thanks!

spark magnet
#

@somber halo i have implemented compute-intensive code in C

somber halo
#

In what general domain was it in? Some sort of scientific computing discipline outside trendy fields like machine learning?

spark magnet
#
  1. mandelbrot calculation 2) code coverage tracing
narrow kettle
#

ive never found a use for it tbh, all my code is IO bound and boring 😒

somber halo
#

ohh, the 2nd's a good one.

flat gazelle
#

yeah, mandelbrot seemed really slow in numpy, compared to pure C or even java.

gleaming rover
#

I feel like if that's the problem

#

might as well put everything after the context managers are entered into another function

somber halo
#

was mandelbrot implemented just for the fun or was it actually an importance piece for some kind of project?

spark magnet
#

just fun 🙂

narrow kettle
#

fair enough

#

ya the double with is def kinda odd

somber halo
#

maybe that's my problem, I'm way too outcome focused nowadays.

narrow kettle
#

my point stands for the singles tho

gleaming rover
#

I like the concept

#

what about async with session = ClientSession()?

#

hm but that makes it very similar to with blocks

#

I find = with quite weird

narrow kettle
#

the = with is weird because it implies an expression i agree

peak spoke
#

Can't really even think of a nice syntax for it, the name won't get the value that the expression returns, the current statement uses as for that reason but that doesn't feel quite right alone and inline

narrow kettle
#

thats where this differs from await

#

its a different type of assignment statement

#

so some form the lhs is probably the best

#
async with session = ClientSession()```this could work but i have a feeling the broader python community would have a harsher reaction to it then say
#
session async with = aiohttp.ClientSession()
#

i personally have always found python to be defined by how you declare a var name as the furthest left token in a statement

gleaming rover
narrow kettle
#

ahh very true

gleaming rover
#

the difference is

narrow kettle
#

and del kinda

gleaming rover
#

those don't define

#

but 🤷‍♂️

#

solution: write new language

narrow kettle
#

ill get around to it eventually

#

as for now ill have to content myself with wishful thinking about langs that i use regularly

gleaming rover
#

I would like Python-but-with-some-changes

#

justice for reduce 😡

narrow kettle
#

i basically want pyskell

#

maybe with a JIT and stronger compiler validated typing

#

we actually had a conversation like that a while ago lol

#

and @gray mirage popped in and said that i never forgot it, i was like hmmmm

gleaming rover
#

I would be happy with snake case logging

narrow kettle
#

lol, all langs got the blacksheep

grave jolt
# gleaming rover I would be happy with snake case `logging`

!e

import re


def ensnake(attrmapping):
    class _SnakeCaseProxy:
        def __getattr__(self, attr: str):
            try:
                return getattr(attrmapping, attr)
            except AttributeError:
                snake_case_attr = attr
                camel_case_attr = re.sub(r"_(.)", lambda m: m[1].upper(), snake_case_attr)
                return getattr(attrmapping, camel_case_attr)
    _SnakeCaseProxy.__name__ = _SnakeCaseProxy.__qualname__ =\
        f"_SnakeCaseProxy<{getattr(attrmapping, '__name__', repr(attrmapping))}>"
    return _SnakeCaseProxy()


###
            
import logging

snake_logging = ensnake(logging)

print(snake_logging.get_logger())
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

<RootLogger root (WARNING)>
gleaming rover
#

oh hey

#

I did something like that too

#

🙂

#

but don't worry

#

I fully appreciate how disgusting that is

#

good job

undone hare
#

Hah

static cliff
#

Hello I have a question. Where can I ask?

undone hare
raven surge
#
In [1]: dp = [[0] * 3] * 3  # Attempt 0

In [2]: dp
Out[2]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

In [3]: dp[0][0] = 1

In [4]: dp
Out[4]: [[1, 0, 0], [1, 0, 0], [1, 0, 0]] # intresting 

In [5]: dp = [[0] * 3 for _ in range(0, 3)] # Attempt 1

In [6]: dp
Out[6]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

In [7]: dp[0][0] = 1

In [8]: dp
Out[8]: [[1, 0, 0], [0, 0, 0], [0, 0, 0]] # what I expected

In [9]:

This surprised me, debugging that, wasn't fun.

winged jetty
#

You have the same underlying list being shared in the first instance

undone hare
#

That's something sadly not really clear in most python tutorial, values are passed around as references, not copied

spice pecan
#

all values are passed around as references, assignment never copies

flat gazelle
#

slices copy on bytearray and list

#

they do not copy on e.g. numpy arrays

proven halo
pure hazel
#

hellow , i am designing a gui with pyqt5,and i want to set a image as a button ,How do i do that?

proven halo
#

oh no, deepcopy not work

from copy import deepcopy
dp = [deepcopy([0] * 3)] * 3
dp[0][0] = 1
dp
# [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
#

so only list generator is safe?

brave badger
#

You're deepcopy-ing the inner-most layer, [...] * 3 still copies the same [...] reference

proven halo
#

Thanks