#internals-and-peps
1 messages · Page 85 of 1
I did repost in data-science earlier, but i thought it'd fit in this channel as well
can anyone help me with my cw?
you can get help with that in #career-advice
What do you guys think about PYTHONPATH
what about it?
Anyone here for urgent help ?
Hey @unkempt rock, see #❓|how-to-get-help
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?
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
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
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)
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
@signal bear if you have a specific issue, maybe I could help you in a help channel
@grave jolt ping me if you're around I'm going to be working for a while, we can jump into a help channel
okay, I'll be around for the next few hours
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?
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?
If you want to run third-party mods in your game, Lua seems to be a popular choice, don't know about its sandboxing capabilities, though.
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 😛
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)
Lua is designed to be sandboxed like JS but more
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
@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
plain setup tools or rust-setuptools
@tulip hazel wrong channel, see #data-science-and-ml or #❓|how-to-get-help
@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
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
@grave jolt how would you defend against attacks like meltdown/spectre/rowhammer? 🙂
well... if your low-level stack is exploited, you're screwed
does anyone have experience with the markdown library in python?
like, the possibility of a nuclear war doesn't prevent us from discussing safety of elevators
If you have a question or an issue, you should claim a help channel (see #❓|how-to-get-help) and explain your problem
thanks
@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
for rust that would be maturin
If you're really worried that people would exploit zero-day bugs in the Lua sandbox which, apparently, is used by many games for many years, the only option is to make your own in-game DSL that doesn't even have the concept of accessing the network or the filesystem.
literally maturin build compiles and packages the wheels
I'm not sure what the threat model of the Lua library as used in games is. 🙂
its generally in a VM so not much it wants to care about
I really want the game to run python code, though... I will look into sandboxing a subprocess, maybe there is something in it there...
Maybe you should ask in #cybersecurity.
then run it in something like a Jail e.g. NSJail (Like @fallen slate 's eval does) or a VM etc...
ok thanks fix error
@radiant fulcrum thanks, will look at that
pretty sure it supports CFFI, PyO3 and Rust-Cpython now
so that should be all bases really
i don't care so much about rust in this case as trying to understand how the tools are set up
cant really explain but on that front generally confused the shit out of me until they released maturin making it alot cleaner
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
In that space right now are maturin and setuptools-rust, as has been said, and both of those are much more rust-focused, and the author of maturin has written this (although noted as slightly outdated) on the subject https://blog.schuetze.link/2018/07/21/a-dive-into-packaging-native-python-extensions.html, but it actually doesn't seem to applicable here.
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.
I did a quick search, and I'm seeing https://github.com/mre/hyperjson using maturin, and seems to be cleanly configured if not release-grade software
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.
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
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
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?
how is being able to override the builtins in a module bad thing, that u would want to avoid it?
In CPython, looking up a bulit-in like print or input is the same as looking up any other global variable, i.e. it's a dictionary lookup. So if builtins were nailed to the code like constants, there could be some performance increase.
o
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.
Hello
!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()
@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
this is the resulting bytecode:
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
Is this really the best solution for type hinting a return value that represents a dict of a JSON object:
https://gist.github.com/BMDan/ede923f733dfdf5ed3f6c9634a3e281f
I found it here: https://github.com/python/typing/issues/182
A comment in this thread details how to define a JSON type
https://github.com/python/mypy/issues/731
@unkempt rock not the correct channel for that
There’s a couple of short solutions in the middle but the last couple of comments have much more complex looking solutions, and I feel none the wiser as to what the solution is haha
It's a lot of boilerplate for the sake pf type safety, that's for sure
Apart from actually having to do the lookup which is unnecessary in most context as you said, builtins will also be slower than both locals and globals as they're the last thing that gets looked at
^^
So if builtins were nailed to the code like constants, there could be some performance increase.
Cython does this by default, fwiw. https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#Cython.Compiler.Options.cache_builtins
You need to opt out of that optimization if you want full Python compatibility
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.
It (almost) was my first language, and I think it is a really good choice
@undone hare It’s using in your job?
I don't have a job, I'm still at school :D
Hi this is the Django web app that I have developed.
It visualizes your WhatsApp chat..
https://chatanalytica.herokuapp.com/demo
Please review it
Review it please
@past sail 👍💯
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
You can do it manually by
Instance1.a == instance2.a
Thanks @high solar
i was wondering if we could define a dunder method that when called gives a list of variables that are not default?
Ohh I never heard about it
You can get all the attributes of a class as a (key, value) using my_object.__dict__.items()
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
oh, that's cool
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.
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?
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
I guess that's what I was sort of thinking with "the hold up in getting the elements"
The iterator for a list just has to keep an index around and accesses the array directly, while a generator has a lot more to do https://github.com/python/cpython/blob/master/Objects/genobject.c#L569-L581
makes sense
Is that linked to:
Which again... why I'm not sure. Perhaps since a list is definitely finite
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
Which was my initial guess
well, yielding from a generator is really sending None to it, which involves some machinery
What do you mean by sending None to it?
is there a way to change just the name of a method in a python class during runtime..
sorry, misspoke -- calling next on a generator is sending None to it
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
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
1234
You only need to use .send(None) start your generator if it should be taking input x = yield
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 }))
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | None
002 | (1, 2, 3)
Explain
I see Maybe 
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
Oh it took me way too long to realise why it printed None haha
Me neither
it would've made sense if the output was 2\n1234 to me, what does yield 1 becomes when you send None?
ah yes, the scary M-word (the other one)
You mean burritos? Anyways, the send/yield feedback loop is a bit hard to get hold of
this explains yield expressions: https://docs.python.org/2.5/ref/yieldexpr.html
Is there a way of printing files through python.
2.5 docs 
"the current yield expression always evaluates to None." Passing None to print doesn't do the same thing though.
printing like real printing
uh no
ok thanks
there probably is
yes i will research
Yeah, there surely is
did he not mean like actually print, a file like print it in paper?
and python has that? anyways 
can someone help me find it??
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
I don't know if it has 'normal' usages
!warn @ionic jetty Stop asking for help with passing an educational system.
:ok_hand: applied warning to @ionic jetty.
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 
not very useful, but kinda interesting.
i used .send in my range implementation of __xor__, __or__, and __and__
since i would iterator over two sorted range sets, and do some operation and if the operation left two disjoint ranges -- the lesser one would be appended to the range set i was constructing and the other one would be sent back into the generator as a "remainder" (https://github.com/salt-die/real_ranges/blob/master/real_ranges/range_set.py#L18)
How the hell r u supposed to deal with cyclic imports when trying to do type hinting
stick imports under if typing.TYPE_CHECKING: ...
another option is -- unsurprisingly -- to not have circular imports 🙂
Very difficult. I want a single _types.py file and in some parts of the module my methods/functions will be annotated with my own classes!
What do you mean? What would go into that file?
I see in there now @peak spoke advice
ah, well, yes, you can do that if some types are shared between modules
how many shared type aliases do you have?
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 🤔
does t pyinstaller also work on linux
It does, though my experience is that it can be fiddly.
Anyone ever work with annotations, descriptors and mypy and how much success have you had ?
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
@crisp wedge this is not the correct channel for that Ask in #game-development
oh thx
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
python has their version of type hints and checks yea
heres a guide on it
You have TypedDict for dicts, and just type hints for regular classes
ah okay thanks @unkempt rock @flat gazelle
I'll check these out
@vivid pewter however small, type hints in python have a runtime cost and are not stripped
What would be this runtime cost?
a few nanoseconds probably, i suppose we should actually benchmark
I wonder how much the difference is between the current and the __future__ implementation.
hey public santa void main a have another challenge if you want i can send u the ansewer but that would be cheating
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
what
I know Flask refuses to type hint because of the runtime cost.
wow, really?
yes
Yeah, the maintainer has shared his views on various issues about the matter
They could add type hints files
It's in typeshed, but that's not really the same
i thought they were essentially just comments
@fleet phoenix This is not a general channel. If you're not here to discuss the language, please find #python-discussion
in the old system they are evaluated
Not too sure how much casts impact performance although I might run into some problems if I start doing them a bit too much
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()```
@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
!e
from __future__ import annotations
class Test:
@staticmethod
def test() -> Test:
return Test()
Test.test()```
@zenith topaz :warning: Your eval job has completed with return code 0.
[No output]
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)
It's almost within the deviation, and tiny compared to even the function call overhead
true, but it makes sense something like that would cause apprehension for a web framework developer to avoid
especially one as big as Flask
Would it be possible for the parser to treat cast as a special case and strip it altogether?
You don't really use it that much with hinting
I use it a bit too much in my lib
I use pydantic which is entirely driven from type hinting 
8 invocations in total but on critical functions; yeah I'm stripping that out lol
I don't think I ever needed to use cast
doesn't assert work as well?
or a directive like # type: ignore
@tidal quiver
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.
That would be dope if true
That's not on-topic for this channel, but maybe ask in #career-advice
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?
What methods do you have in mind?
There's a new thread on python-ideas today proposing async constructors via a metaclass...
setitem and getitiem, so that the api for RedisCache is nicer.
does that mean that classes could inherit from a metaclass where dunder methods wrap around coroutines that do the actual work?
that would also need some alternate syntax, can't think a nice way now
I suppose await thing[a] = b would break the parser
Yes, they can do that today. It's just incredibly surprising if that happens.
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
That get would conflict with its current behaviour
it's more Pythonic: the syntax for setting a value uses the = operator throughout the language
yo
I'm not arguing with you :)
my last two messages just kind of explain my position of why some operations should be overloads of built-in constructs instead of just methods
!resources @coarse jungle -- this is strictly a discussion channel though
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
hmm see I wanna learn it but do I want to do the work to learn it hmmmmm?
yes you are. or at least you are now. 
jk 💚 💚 💚
no I'm not 
:) smile
That's up to you.
hmmmm I feel like some nerd will teach it to me and it will be fine
someone helping you won't eliminate all the effort that you, and no one else, has to put in to learn programming.
I really am not. There are a lot of resources on that page and many people in our community will be happy to help if you end up with specific questions.
it's not possible to learn something by just listening to "some nerd" (unless you believe in supernaturally acquired knowledge)
see what I think is, hear me out. drugs, voicechat, friendships, and yea.
yea know
Anyway, this discussion does not belong here. Please move to off-topic.
oop k
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}
probably the order of the hashtable
Makes sense, but how would the order change in {6, 7, 8, 9} given that these numbers all hash to themselves?
pop returns some value from a set
it can do whatever it wants to choose it
even random.choice, if you want to be silly
time to dig into the source
Right, but it seems deterministic
well, maybe, but you probably shouldn't rely on it 🙂
Right, the numbers hash to themselves, but a hash table isn't ordered by hash value.
@fresh cargo there is no guarantee about the order, so internal details will affect the order
The initial probe index is computed as hash mod the table size.
table size starts at 8
Thanks and I'm aware. I'm more or less curious about the implementation because the above behavior seems weird to me
yeah, i don't know what's going on in there
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?
¯_(ツ)_/¯ 🙂
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
So it multiplies by 4 each time when table size is small. Explains 8 ⇒ 32
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
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
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?
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)
Hey, I’m new but I was wondering if anyone could help me out with a problem. Is this the right chat for that?
Okay cool. Thanks
Is there a reason to use dict.keys() other than readability and symmetry with dict.values() and dict.items()?
dict.keys() is setlike, so you could do set stuff on the keys directly
though thats not particularly common
Most of the time you can just use the dict directly anyways
Technically I can do set(dict_var) though
of course, but I'd imagine its slightly slower
either way, I was just answering the question
Just curious 😛 Thanks to you both
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
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
yeah, Im guessing its O(1) behavior vs O(nlogn)
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
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
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"?
@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.
@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.
I did a bit more reading (more than skimming through) PEP 638 a bit and I think I'm starting to get a feel of https://www.python.org/dev/peps/pep-0638/#matching-symbolic-expressions better than PEP 634
im just learning how to use python
Hey, see #❓|how-to-get-help
ty
@rugged nexus if you wanted to talk about Discord itself, that might be a topic for one of the three off-topic channels.
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.
You can use itertools.repeat.
In the future, use our help system (see #❓|how-to-get-help) to get help. This is a channel for meta-discussions about Python
Alright, sorry @grave jolt.
(can't use itertools.repeat due to requirements, good night!)
you can write your own, it's not a very complex iterator 🙂
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 You're right. The first yield will exhaust the generator.
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++)
@red solar link?
Hmm one sec
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?
@red solar found it
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....
This looks like lifetimes!
@red solar nah that's not it, it changes as I start the interpreter from different directories
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?
different OSes, and slightly different python versions unfortunately (3.7.7 vs 3.7.9), so not a direct comparison
@red solar seems like it would just give typehinters a concept of ownership over a variable
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*
Lol u can still discuss it just cuz smarter people already discussed it
nothing to add :)
Sh33mp gimme a sec to try it out on my windows+Linux
it's centos vs ubuntu
ah :/ then i'm even more surprised 
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
yee
wow this is so much better than following it through email
ah, man, if you have one of the tree-threaded clients it makes it easier to follow, too
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
No I do not. I don't know of any on mobile :(
@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
oh weird, I got it
What was it?
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)
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
can you do that? add a question and answer it yourself
oh, there it is https://stackoverflow.com/questions/33615156/why-does-pythonpath-with-trailing-colon-add-current-directory-to-sys-path
unfortunately when I was searching this didn't come up
thanks anyway!
hmm didn't appear for me either - glad you found it tho 🙂
anyone have resources to get better at solving algorithm problems
@indigo yarrow what is a 3 headed client
@paper echo lol. Medusa, release v3.3
In case you legitimately misread:
tree - forked or branched
threaded - related by ancestry
client - for email
@paper echo
eg.
It is not real. It was an attempt at humor based on your misunderstanding.
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())
@brave badger :white_check_mark: Your eval job has completed with return code 0.
helloworld
@north root @low lagoon See 
I assume it's a leftover feature from the old days
what I'm more interested in is
how did you discover that
Oh mb I was in ahelp channel and they told me to come here
That's what I want to ask f1re as well, they tried it with True initially
#data-science-and-ml would be good
Alright thank you!
Figured it was a Unix thing https://en.m.wikipedia.org/wiki/File_descriptor. I guess patching stdin works as well, just not with snekbox.
interesting
i was running what @shrewd dune wrote #ot1-perplexing-regexing message
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
that's probably just something trying to close stdout twice.
try:
open(True, 'wb', closefd=False).write(b'Hi\n')
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.
>>> with open(True, 'wb') as f:
... f.write(b'hello\n')
...
5
hello
>>> exit()
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
well: when a program starts up, there's no guarantee that file descriptor 1 or 2 are open.
so?
The question is, does it pull them from sys.stdout/stdin/stderr or is it capable of opening them?
well, as far as 1/2 are concerned, that probably depends a lot on OS.
oh yeah this is probably unix-specific
technically I think the only guarantee you get is that the default stdout is STDOUT_FILENO, I think
and likewise with STDERR_FILENO
other os's dont have stdout_fileno
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
more implementation specific:
>>> x=open("asdf","w")
>>> open(3,"w").write("Hello")
5
>>> y=open("asdf","r")
>>> open(3,"r").read()
'Hello'
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
this was an interesting question. Interestingly, it tries to write to them despite the fact that they're not open, and gets an EBADF on each write.
so, it's a Unix implementation detail that fd's are allocated sequentially, and guessing that open returned 3 isn't portable (and, if 3 was open already when the interpreter started, this guess would be wrong). But Python does require that the return from os.open() can be passed to open()
@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 actually, not reallywrite and the REPL trying to echo it
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
lmao
it's like when someone refuses to listen to your arguments
just cover your ears.
were you who tried to do ~await x?
this was months ago and I never told you...
it doesn't say why, but they said it's not valid
asdf not this one, this one is valid
!e
async def f():
-await x
@grave jolt :warning: Your eval job has completed with return code 0.
[No output]
but - is fine?!
wait, no, I did a different thing
I did await ~x
!e
async def f():
await ~x
@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
yep
oh okay
!e
async def f():
await -x
@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
alright, I could've just done await x xD
the whole project was an... "exploration"
I was replicating the IO monad from Haskell
btw, related to the previous conversation, you could always get the proper file descriptor from sys.stdout.fileno(), but it was a joke snippet
Hello, anyone here moderately experienced in pyQt?
this is a channel for language discussion
you can try #user-interfaces
thanks
who founded this discord server? Was it @fossil pumice?
@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 )
Thanks
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
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__.
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
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
inst that like the entire point of a context manager
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"
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
You can already use multiple objects in a single with though IIRC
Not sure about async with
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
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
Don't think I've ever had a problem with the indentation a with block introduces
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
Does this actually work?
its what i do for multiple files
Didn't test the parens, but in a single line yeah, it works
cool
im not sure if it works for things like this tho
It should in 3.9
I remember a mailing list submission for implicit line continuation in such cases
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
the old parser will fail with it and needs the backslash continuation
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
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>```
@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
oh right
does that work for async with
you see the point
i need some help with base64 in python
not sure about async
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
this isnt a help channel @quiet nebula you can see #❓|how-to-get-help for more info
i also already gave you an example of base64
@narrow kettle im new in discord too, i needed help and i join here, sry bro
I personally don't agree, but I wouldn't mind having that either
To me it feels like it'd encourage to keep resources open unnecessarily long
^
i mean if your functions are long enough that this is a problem then thats major code smell imo
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
im not following
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
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
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
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
I try to flatten the code wherever possible, but a with block never really felt problematic to me in that regard
i have a fair amount of async with requests with aiohttp
the "pyramids" have alwasy bothered me
@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.
:incoming_envelope: :ok_hand: applied warning to @unkempt rock.
@narrow kettle no, creating a new indent level is good
Excuse me
In this case it’s not being explicit, it’s a break from other behaviors
wdym
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
ok it kindof is overloading the concept of indentation
The general usage of a with block that I’ve seen basically are just wrapping the entire contents of a function in the with
But it is much better than just a statement
That’s a needless level of indent
then those functions are poorly written
ok that's fine
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
this pattern seems to encourage leaving resources open for the entirety of a function
That’s already what happens
just like it would be without context managers
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
this still seems like it would encourage bad practices
since its only really good if you use small functions
and thats a big if
We are all adults here is what quido says
There is TONS in python that encourage bad habits
It’s very open
like what
But it allows you to express CORRECT patterns in a much simpler way
The entire language? There is almost no concept of safety in py
Access control doesn’t exist, reflection is as easy as one or two calls
it seems more complex to me
All these things encourage shitty code while also allowing for idiomatic expressions in different cases
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
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
with blocks are supposed to make it easy for you to manage scope
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
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
compare
My solution already exists in other Lang’s and it works great, it IS a tried and tested solution tbf
I didn’t come up with this
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
there's more actually
most of them came as C++ legacy IIRC, but yeah
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
and c++ isn't exactly a well designed language
Modern c++ is pretty nice
too much legacy c stuff
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
I don’t get the point of these two snippets, call .close at the end and they are the same
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
imports also flip lhs and rhs
and the new indents are good
because it clearly shows that its within a with block
This is an import tho, but yes it’s also confusing here as well
i dont quite see how one level of indent creates more mental load
One isn’t necessarily bad, it’s when they are nested that it gets bad
I wouldn't call new indents mentally heavy, if anything they help see where the resource is acquired and where it is released
^
Though yeah, nesting can be an issue ig
In practice, for the majority of operations you don’t NEED to know exactly when it is released
uhhh
Having an open file for a few extra micro seconds while the function ends is not bad at all
If you NEED a fine grained control then you probably want the with block or even a try finally
is so you know exactly when it is released
and that applies to all resource managment
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
But the point remains, keeping a resource open for slightly longer then you need it is not necessarily bad
which is bad
Yes they do
its not explicit
It’s just as explicit as a white block
It happens at the end of the scope, but python and C# handle scopes differently
“When indentation ends”
and with resource managment, its really better if releasing resources is explicit
if condition:
x = with resource
do_stuff(x)
should that work, for example?
A with block is not more explicit then a statement about “releasing resources” it’s slightly more explicit about WHEN
Yes
Tho that is up for discussion for sure
It could go both ways
For the sake of consistency with python, it should work
I generally agree
but in, say, C#, ifs and flow control statements alike precede a new scope
python doesn't have block scoping unlike c#
Well i mean it has function scoping
yes and that is a good thing
Which is similar and in practice often the same thing
It’s also not important in most cases
block scoping is very different from function scoping
I’m saying well written python has functions that are chunked up into scopes that fairly closely mimic block scope
key word is "well written"
Your misunderstanding, I’m not saying it’s not important to close resources
I’m saying it’s not important to have fine tuned control of it when the difference is mostly just a few lines
well if you don't care when your resources are released, it's basically the same thing
That’s picosecodns of difference
There’s nuance here, i don’t care if it’s released on say line 33 or line 40
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
assuming best practices, yes
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
and that is a bad thing
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
it seems too easy to abuse
Everything in python is easily abused
That’s part of what makes it so fun and dynamic
like monkey patching can be abused
but you don't see any beginners going around abusing it
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
ah yes magically discarded somehow
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
seems to me like encouraging bad practices of not caring about resource lifetimes
and it's bad that it's simple
oop had to step away for a second,
its not NOT caring about resource lifetime, its recognizing that a few lines of difference is not something to think about
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.
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
and if you are somehow DOING long running single threaded work in that one function then that work SHOULDNT be in that function
im not anti with block, it will still exist when you want it
im just offering a simpler use case scenario for something i run into alot
I'm just typically annoyed myself by not closing out the resource lol
and a feature that i USE all the time in other langs
like OCD or something
then youll probably be more likely to close out the resource if its just the addition of one keyword
Yeah I mean with something that small closing vs closing when the program terminates is negligable
with open() as f:
pass
vs
f = with open()
right, so I use with so I know it is closed when finished
most people dont even close the file in scripts, os does it for you
that was my point
so the beginner/script arguement kinda loses some validity there
this isnt something for that usecase
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
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
there are def some valid questions about say this case #internals-and-peps message
but imo its something iwth very few drawbacks and a high upside
python already has a really bad habit of becoming a "sideways pyramid"
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
thats not the point
the point is that one makes it clear where the scope begins/ends
and the other doesn't
this is nothing like goto at all in any way
i mean its very clear, the end of the function, clarity is not the problem
its the same clarity as you know where the variables scope ends
yes, its implicitly closed at the end of the scope
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
yeah because scoping is shown via indents
not necessarily
you switched it
python doesn't have block scope
the with block is a BREAK from traditional python
no it s not
its not normal behavior
why not?
i mean you can access the with block's var after the function
which is why it has diff assignement semantics
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
its not redundant
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
the indent helps you clearly know what the lifetime of the variable is
not in this case
yes it does
its the same
lifetime until the function ends is pretty indicative
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
my point about the with block was that the vast majority of python scope is done at the function level
its the standard pattern
whats the lifetime of that
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
you keep saying the with statement is unclear, but its quite literally the standard way to read python
no like
i mean the syntax it self is changeable
its too easy to miss the fact that this variable has auto-closing
^
and its weird that an expression affects the entire function's behavior
elaborate
i mean speaking from experience its really not
like not at all thats a non issue
ok what would be the behavior of print((with open("file.txt")).read())
i mean i said a with STATEMENT not a with expression
hol up
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
there's one extra level of nesting here I guess
(minor point)
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
async with ClientSession() as session, await session.get(url) as response:
if (response.status) == 200:
pass
not really sure if it's worth it
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
not to me, but 🤷♂️
you prefer that over the double with?
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
maybe #c-extensions would be more helpful on that front?
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 i have implemented compute-intensive code in C
In what general domain was it in? Some sort of scientific computing discipline outside trendy fields like machine learning?
- mandelbrot calculation 2) code coverage tracing
ive never found a use for it tbh, all my code is IO bound and boring 😒
ohh, the 2nd's a good one.
yeah, mandelbrot seemed really slow in numpy, compared to pure C or even java.
yes
I feel like if that's the problem
might as well put everything after the context managers are entered into another function
was mandelbrot implemented just for the fun or was it actually an importance piece for some kind of project?
just fun 🙂
maybe that's my problem, I'm way too outcome focused nowadays.
my point stands for the singles tho
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
the = with is weird because it implies an expression i agree
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
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
precedent is global and nonlocal
ahh very true
the difference is
and del kinda
i always end up coming back to this 🤣
ill get around to it eventually
as for now ill have to content myself with wishful thinking about langs that i use regularly
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
I would be happy with snake case logging
lol, all langs got the blacksheep
!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())
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
<RootLogger root (WARNING)>
oh hey
I did something like that too
🙂
but don't worry
I fully appreciate how disgusting that is
good job
Hah
Hello I have a question. Where can I ask?
Hey @static cliff, see #❓|how-to-get-help 
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.
You have the same underlying list being shared in the first instance
That's something sadly not really clear in most python tutorial, values are passed around as references, not copied
all values are passed around as references, assignment never copies
is it a good idea that use copy.deepcopy() when we are not sure
hellow , i am designing a gui with pyqt5,and i want to set a image as a button ,How do i do that?
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?
You're deepcopy-ing the inner-most layer, [...] * 3 still copies the same [...] reference
Thanks