Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
QuarkJets
Sep 8, 2008

Hughmoris posted:

I'm trying to make me program easier for my users and am a bit stumped on something.

We have an account number that ends in a Julian date. For instance: 22365003. I need to key off of the last four numbers, the "5003". The "5" is for 2015, and the "003" is the third day of the year. So the date associated with this account number is 01/03/2015.

With an account number of 436114028, I'd like to know that the associated date is 01/28/2014.

Any ideas on how to convert the last four numbers to a date format of MM/DD/YYYY?

Use any scheme you want for grabbing the days and year values (are these integers or are they strings?), and then from there use the timedelta and date objects to get a Julian date

Python code:
account_number = 436114028
key_digits = account_number % 10000 # returns 4028
day_value = key_digits % 1000 # returns 028, which is just 28
year_value = int(((key_digits - day_value)) / 1000 + 2010) # returns 2014

#convert number of days to a datetime
from datetime import date, timedelta
td = timedelta(day_value - 1)
date = date(year_value, 1, 1) + td

print date
This prints out 2014-01-28. The more interesting test case is for 32 days, since that should push you to a new month: 436114032 prints out 2014-02-01. This script is producting a date object, fyi

Adbot
ADBOT LOVES YOU

Liam Emsa
Aug 21, 2014

Oh, god. I think I'm falling.
So all of my experience in Python is in data analysis, numerical analysis, mathematical computation, etc. It isn't proving good for landing Python development jobs. Where would be a good place to start learning that side of Python?

Hughmoris
Apr 21, 2007
Let's go to the abyss!

KICK BAMA KICK posted:

Python code:
import datetime as dt

def acct_to_date(acct_no):
    """
    acct_no: str
    return: datetime.date
    """
    last_four = acct_no[-4:]
    year_offset, day_offset = int(last_four[0]), int(last_four[1:]) - 1
    date = dt.date(2010 + year_offset, 1, 1) + dt.timedelta(days=day_offset)
    return date
That's a basic idea; you can futz the input and output into whatever format you like and you'd definitely want to add some sanity checks.

Thanks for this. I'll play around with it. I tried it with an account number of 53525042 and it threw a fit. Something about : int base must be between 2 and 36.

KICK BAMA KICK
Mar 2, 2009

Hughmoris posted:

Thanks for this. I'll play around with it. I tried it with an account number of 53525042 and it threw a fit. Something about : int base must be between 2 and 36.
Weird, I don't have any problems on Python 2 or 3 with that input, returns 2015-02-11 for me.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

KICK BAMA KICK posted:

Weird, I don't have any problems on Python 2 or 3 with that input, returns 2015-02-11 for me.

I'm trying to copy from a phone screen so I'm probably missing a character. I'll get the chance to look at it tonight.

QuarkJets posted:

Use any scheme you want for grabbing the days and year values (are these integers or are they strings?), and then from there use the timedelta and date objects to get a Julian date

Python code:
account_number = 436114028
key_digits = account_number % 10000 # returns 4028
day_value = key_digits % 1000 # returns 028, which is just 28
year_value = int(((key_digits - day_value)) / 1000 + 2010) # returns 2014

#convert number of days to a datetime
from datetime import date, timedelta
td = timedelta(day_value - 1)
date = date(year_value, 1, 1) + td

print date
This prints out 2014-01-28. The more interesting test case is for 32 days, since that should push you to a new month: 436114032 prints out 2014-02-01. This script is producting a date object, fyi

Thanks. I'm going to play these tonight and see what I can do.

duck monster
Dec 15, 2004

Liam Emsa posted:

So all of my experience in Python is in data analysis, numerical analysis, mathematical computation, etc. It isn't proving good for landing Python development jobs. Where would be a good place to start learning that side of Python?

I dunno. Where I worked last (In australia) they where always on the hunt for people who could understand what the loving physicists where trying to do and make it into proper code.

That said the government went cutback crazy and dumped our whole department, because science is for nerds and not conservatives apparently.

Hughmoris
Apr 21, 2007
Let's go to the abyss!
Python has spoiled me. I'm tinkering around on a new project where we have a 60,000 line log file and want to pull out lines relevant to a user_id. I wrote an ugly but functional script to satisfy the user's needs, within an hour. That includes googling problems I ran into and figuring out how to use regex. It amazes me at how beginner friendly Python is, and how a novice can get real work done with it.

I was originally looking at writing it in a .NET language because I'd like to make it nice and easy to get to my coworkers in an all Windows environment. Since I don't know any .NET languages, I figured I'd tackle it in Python. Easy breezy. Now I'm back to the headache of distributing a Python script.

Hughmoris fucked around with this message at 04:26 on Mar 1, 2015

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Python basically exists as that language you write extremely dirty one-off scripts in and never want anybody to see ever.

QuarkJets
Sep 8, 2008

Hughmoris posted:

Python has spoiled me. I'm tinkering around on a new project where we have a 60,000 line log file and want to pull out lines relevant to a user_id. I wrote an ugly but functional script to satisfy the user's needs, within an hour. That includes googling problems I ran into and figuring out how to use regex. It amazes me at how beginner friendly Python is, and how a novice can get real work done with it.

I was originally looking at writing it in a .NET language because I'd like to make it nice and easy to get to my coworkers in an all Windows environment. Since I don't know any .NET languages, I figured I'd tackle it in Python. Easy breezy. Now I'm back to the headache of distributing a Python script.

Distributing the script is easy, you just need to get your recipients to install Python so that they can actually run it

Brotato Broth
Feb 21, 2012
I'm trying to get aalib working in OS X without much success.

This is what I get whenever I try to import it in 2.7.9:
code:
>>> import aalib
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "aalib.py", line 29, in <module>
    libaa = ctypes.CDLL('libaa.so.1')
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(libaa.so.1, 6): image not found
Googling the problem doesn't seem to yield anything useful. What can I do about this?

QuarkJets
Sep 8, 2008

Brotato Broth posted:

I'm trying to get aalib working in OS X without much success.

This is what I get whenever I try to import it in 2.7.9:
code:
>>> import aalib
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "aalib.py", line 29, in <module>
    libaa = ctypes.CDLL('libaa.so.1')
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(libaa.so.1, 6): image not found
Googling the problem doesn't seem to yield anything useful. What can I do about this?

It's trying to load a shared library (libaa.so.1), but it's not able to find it.

First, make sure that you have aalib installed. And I mean installed, not just compiled in some random location.

If aalib is installed, see if you can find libaa.so.1 yourself, wherever libaa installs its shared libraries. It's possible that the Python aalib module has a hardcoded library name of libaa.so.1, but maybe the installed file is just libaa.so. You can fix this by just creating a soft link to libaa.so and calling it libaa.so.1 in the same directory.

If you've found the library, and it exists, and the libaa.so.1 file exists too (as a link or otherwise), and the aalib import still isn't working, then try putting the path to libaa.so.1 in your LD_LIBRARY_PATH.

Brotato Broth
Feb 21, 2012
All I could find that remotely matched the filename was libaa.a and symlinking to that doesn't seem to cut it. Am I not supposed to use Homebrew to install aalib or something?

QuarkJets
Sep 8, 2008

Brotato Broth posted:

All I could find that remotely matched the filename was libaa.a and symlinking to that doesn't seem to cut it. Am I not supposed to use Homebrew to install aalib or something?

It sounds like Homebrew creates special directories for everything and them places symlinks where the libraries would normally be installed, in which case it's possible that it's linking to the wrong library.

It's also possible that the package that you've installed with Homebrew is a version that is incompatible with the python module; it's possibly that the name of the file has changed at some point.

Either way, what you found was a static library, and you need a shared library. You might have to compile the library yourself

syncathetic
Oct 21, 2010

Brotato Broth posted:

All I could find that remotely matched the filename was libaa.a and symlinking to that doesn't seem to cut it. Am I not supposed to use Homebrew to install aalib or something?

It looks like homebrew only builds the static version of the library. You can create a dynamic library from the static one:

code:
cd /usr/local/Cellar/aalib/1.4rc5/lib
clang++ -shared -Wl,-all_load libaa.a -o libaa.dylib -lcurses
ln -s /usr/local/Cellar/aalib/1.4rc5/lib/libaa.dylib /usr/local/lib/libaa.dylib
Then you need to replace "libaa.so.1" with "libaa.dylib" in aalib.py.

duck monster
Dec 15, 2004

Brotato Broth posted:

All I could find that remotely matched the filename was libaa.a and symlinking to that doesn't seem to cut it. Am I not supposed to use Homebrew to install aalib or something?

libaa.a is no a .so file, but it can be linked into one. Uh, my C chops are probably not good enough enough to tell you what to link it to though.

You could try something like gcc -shared -o aalib.so -laalib.a but I'm not sure how well that will work if its not positition independent code. -fPIC or something like that I guess? There might also be some mac specific things needed I dunno

edit: Beaten to it. ^^^^ That version looks more plausible than mine.

Brotato Broth
Feb 21, 2012
Thanks for the help, but I'm still getting the same error with different filenames even in interactive mode:

code:
>>> import aalib
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/aalib.py", line 29, in <module>
    libaa = ctypes.CDLL('libaa.dylib')
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(libaa.dylib, 6): image not found
As far as I can tell, compiling was successful and everything is where it should be:

code:
$ find -f /usr/local "libaa\.dylib" | grep libaa\.dylib
/usr/local/Cellar/aalib/1.4rc5/lib/libaa.dylib
/usr/local/lib/libaa.dylib

unixbeard
Dec 29, 2004

LD_LIBRARY_PATH becomes DYLD_LIBRARY_PATH on os x, so try

env DYLD_LIBRARY_PATH=/usr/local/lib python -c 'import aalib'

It usually gets ignored if you are running as uid 0 as well

onionradish
Jul 6, 2006

That's spicy.
I have scripts written in 2.7 that I want to start prepping for a migration to 3.x later this year. The scripts still need to run in 2.7 until then. One of the first things I'm looking at is ensuring I'm specifying Unicode for string literals (u'my string') in these scripts -- which hasn't been done consistently.

My first inclination is to pre-pend the 'u' marker on string literals manually or using something like this StackOverflow code which tokenizes Python code and adds the 'u' to string literals automatically. The default SO code is aggressive and pre-pends the 'u' to docstrings and string parameters like open(filename, u'r'), which seems excessive, but may be "correct." I've modified that code to output an 'after' file so I could do a diff against the source and manually merge changes where they make sense, but I haven't done so yet.

Is adding 'u' everywhere a reasonable approach to making my scripts more compatible for the eventual migration? Or should I use from __future__ import unicode_literals? I could do nothing for now and just deal with any issues when running the script in Python 3 or let helpers like 2to3 fix or alert me to issues, but I'd like to minimize headaches later.

Brotato Broth
Feb 21, 2012

unixbeard posted:

LD_LIBRARY_PATH becomes DYLD_LIBRARY_PATH on os x, so try

env DYLD_LIBRARY_PATH=/usr/local/lib python -c 'import aalib'

It usually gets ignored if you are running as uid 0 as well

Huh, this managed to fix it. My thanks to everyone who responded.

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug

onionradish posted:

from __future__ import unicode_literals

This is what I usually do for 2/3 compatible code, along with importing print_function and division.

KICK BAMA KICK
Mar 2, 2009

Here's a pattern I have need for in a few places, and I'm wondering what the right way to go about this is, in terms of general design and specifically Pythonicity. I want to generate some Foos and assign values to any number of attributes upon generation. In different cases, the caller may want to generate these attributes in different ways -- often randomly but maybe with different distributions, sometimes just assigning the same value, etc. Here's a mock-up of the first idea I came around to.
Python code:
def generate_foos(n, **kwargs):
    """
    n: int, number of Foos to generate
    kwargs: Optional arguments specifying how to set attributes of generated Foos. 
     If given, should be callables which take no argument and return a value of appropriate type.
        bar: string; defaults to selection from a predetermined list
        baz: int; defaults to a random value on a uniform distribution from BAZ_MIN to BAZ_MAX, inclusive
        qux: datetime.date; defaults to Jan. 1, 1970
    return: List of Foos
    """
    # Set up attribute generation functions, from kwargs if given or defaults if not
    get_bar = kwargs.get('bar', lambda: random.choice(BAR_OPTIONS))
    get_baz = kwargs.get('baz', lambda: random.randint(BAZ_MIN, BAZ_MAX))
    get_qux = kwargs.get('qux', lambda: datetime.date(1970, 1, 1))
    # Generate
    foos = []
    for _ in range(n):
        foo = Foo()
        foo.bar = get_bar()
        foo.baz = get_baz()
        foo.qux = get_qux()
        foos.append(foo)
    return foos
Is that how you use kwargs? I remember a discussion a while back bringing up that PEP 8 explicitly prohibits assigning lambdas to a name so those could be pulled out into functions of their own in real code. Does the API in general make sense?

e: I do see it's customary to use kwargs.pop() in place of kwargs.get() to allow you to later check if any extraneous arguments were passed.

KICK BAMA KICK fucked around with this message at 02:16 on Mar 3, 2015

salisbury shake
Dec 27, 2011

KICK BAMA KICK posted:

Here's a pattern I have need for in a few places, and I'm wondering what the right way to go about this is, in terms of general design and specifically Pythonicity. I want to generate some Foos and assign values to any number of attributes upon generation. In different cases, the caller may want to generate these attributes in different ways -- often randomly but maybe with different distributions, sometimes just assigning the same value, etc. Here's a mock-up of the first idea I came around to.
Python code:
def generate_foos(n, **kwargs):
    """
    n: int, number of Foos to generate
    kwargs: Optional arguments specifying how to set attributes of generated Foos. 
     If given, should be callables which take no argument and return a value of appropriate type.
        bar: string; defaults to selection from a predetermined list
        baz: int; defaults to a random value on a uniform distribution from BAZ_MIN to BAZ_MAX, inclusive
        qux: datetime.date; defaults to Jan. 1, 1970
    return: List of Foos
    """
    # Set up attribute generation functions, from kwargs if given or defaults if not
    get_bar = kwargs.get('bar', lambda: random.choice(BAR_OPTIONS))
    get_baz = kwargs.get('baz', lambda: random.randint(BAZ_MIN, BAZ_MAX))
    get_qux = kwargs.get('qux', lambda: datetime.date(1970, 1, 1))
    # Generate
    foos = []
    for _ in range(n):
        foo = Foo()
        foo.bar = get_bar()
        foo.baz = get_baz()
        foo.qux = get_qux()
        foos.append(foo)
    return foos
Is that how you use kwargs? I remember a discussion a while back bringing up that PEP 8 explicitly prohibits assigning lambdas to a name so those could be pulled out into functions of their own in real code. Does the API in general make sense?

e: I do see it's customary to use kwargs.pop() in place of kwargs.get() to allow you to later check if any extraneous arguments were passed.

I usually use **kwargs to collect arguments with names that I don't explicitly know and intend to pass on to another function/method. Otherwise, I feel that being explicit with the parameters your function takes would be the best bet here since you explicitly check for certain kwargs in the function body.
Python code:
def generate_foos(n, bar: FunctionType = None, baz: FunctionType = None, qux: FunctionType = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
	if baz is None:
		baz = lambda bf9uriuhri: foirfo4rfo
	etc 
If you were doing something more dynamic with your kwargs, I can see pattern matching with **kwargs and doing something with each parameter/value pair being clearer.

QuarkJets
Sep 8, 2008

I'll sometimes use kwargs if I have an excessive number of optional parameters that are passed between multiple functions or classes, but otherwise I think that it's better to just use keyword arguments if your parameters are optional

salisbury shake posted:

Python code:
def generate_foos(n, bar: FunctionType = None, baz: FunctionType = None, qux: FunctionType = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
	if baz is None:
		baz = lambda bf9uriuhri: foirfo4rfo
	etc 

I've never seen "FunctionType" in a keyword definition before. What does that do?

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

QuarkJets posted:

I'll sometimes use kwargs if I have an excessive number of optional parameters that are passed between multiple functions or classes, but otherwise I think that it's better to just use keyword arguments if your parameters are optional


I've never seen "FunctionType" in a keyword definition before. What does that do?
It's part of the types library: Type which specifies that it's a user defined function and lambdas.

KICK BAMA KICK
Mar 2, 2009

Thanks, explicitly named kwargs does seem better. I did just realize I can leave it as **kwargs until I nail down all the attributes and then put them all in the signature without changing the interface for callers, which is pretty nice. And this seems like a situation to use that lone * in the argument list to mandate that they're only passed by keyword.

accipter
Sep 12, 2003

KICK BAMA KICK posted:

Thanks, explicitly named kwargs does seem better. I did just realize I can leave it as **kwargs until I nail down all the attributes and then put them all in the signature without changing the interface for callers, which is pretty nice. And this seems like a situation to use that lone * in the argument list to mandate that they're only passed by keyword.

I pretty much only use '**kwds' with class methods that with inputs that vary between different classes.

QuarkJets
Sep 8, 2008

Master_Odin posted:

It's part of the types library: Type which specifies that it's a user defined function and lambdas.

I'm still confused as to what purpose it serves. IE, what's the difference between

Python code:
def generate_foos(n, bar: FunctionType = None, baz: FunctionType = None, qux: FunctionType = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
and

Python code:
def generate_foos(n, bar = None, baz = None, qux = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
Does it trigger some sort of optimization or something?

KICK BAMA KICK
Mar 2, 2009

QuarkJets posted:

I'm still confused as to what purpose it serves. [...] Does it trigger some sort of optimization or something?
I think that's just a function annotation, which are optional and not interpreted by Python itself but used for documentation and maybe some tools. I had seen the syntax before but didn't know FunctionType or that it could be used like that with a default value.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Its used for the static type checker myPy and tools like PyCharm use it for type hinting.

salisbury shake
Dec 27, 2011

QuarkJets posted:

I'm still confused as to what purpose it serves. IE, what's the difference between

Python code:
def generate_foos(n, bar: FunctionType = None, baz: FunctionType = None, qux: FunctionType = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
and

Python code:
def generate_foos(n, bar = None, baz = None, qux = None):
	if bar is None:
		bar = lambda: random.choice(BAR_OPTIONS)
Does it trigger some sort of optimization or something?

https://www.python.org/dev/peps/pep-3107/

Function annotations can help convey the intention of what the function expects to take as parameters. The standard Python interpreter doesn't check them, but they're accessible in ___annotations__. They shine in PyCharm, though.

edit:
this post by guido pep is cool. I'm not a typing purist, I just want to use auto-complete more often.

salisbury shake fucked around with this message at 03:17 on Mar 4, 2015

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
I'm getting back into Python development and I'm in a bit of a bind. I'm working with non-ASCII characters and I can't use Windows' command prompt to preview foreign text that I output with print(). I'm also using virtualenv to sandbox everything, but none of the alternative command prompts I've tried supported running the activate script. Is there an IDE I can use that will support UTF-8 output as well as recognize and work with a virtual environment?

SurgicalOntologist
Jun 17, 2004

Karthe posted:

I'm getting back into Python development and I'm in a bit of a bind. I'm working with non-ASCII characters and I can't use Windows' command prompt to preview foreign text that I output with print(). I'm also using virtualenv to sandbox everything, but none of the alternative command prompts I've tried supported running the activate script. Is there an IDE I can use that will support UTF-8 output as well as recognize and work with a virtual environment?

Any IDE worth using, and many text editors, meet those requirements. Try one of PyCharm, Spyder, or Sublime Text 3 (with a Python plugin).

Also did you try a terminal emulator? Something like ConEmu should work for unicode characters (I think). The activate script will certainly work.

SurgicalOntologist fucked around with this message at 09:31 on Mar 5, 2015

JawnV6
Jul 4, 2004

So hot ...
I'm building a thing in Python because I didn't have a lot of time. I'm bolting the final few features on and have some questions about multithreading.

Right now, I have a single serial port. The main loop does a blocking call to see if it has bytes. If the timeout is hit instead of characters being available, it does some updates internally. I was hoping to get something working with a GPIO interrupt (RPi hooks for this allow for an explicit callback function) but it's not happening. I'm probably going to have to use a second serial port.

I can muck around with the two devices and figure out which one's which. But I'm not sure how to structure the superloop now. Here's the skeleton of the existing code:
Python code:
#!/usr/bin/python

import serial, subprocess, struct, os
import Graphics

graph = Graphics.Graphics()

ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

while(True):
        graph.update()
        command = ser.read(100)
        # If timeout was hit, ignore it and loop
        if(len(command) == 0):
                continue
ser.read(100) is blocking, normally exiting on the timeout. If command is nonzero, there's additional processing that queues up things to the graphics class. Command can be variable length. I need to add an additional serial read for a device that's expected to do a lot less communication.

I'm tempted to just open it with a much, much smaller timeout, add it after the existing read, and slim its communications down to a single character (possible for the second serial port, not the first). Is there some better way to check for activity on a serial port?

e: is select what I should be using for this?

JawnV6 fucked around with this message at 20:25 on Mar 5, 2015

Harriet Carker
Jun 2, 2009

If I have a function with a varaible number of arguments, and I want to do something different depending on the number of arguments entered, is there a better way to do it than the following?

code:
def fun(*args):
    count = 0
    for arg in args:
        count += 1
    if count > 1:
        ...
It's pretty simple to do it this way but my gut tells me there must be some built in or more elegant way.

EDIT: I am a huge dummy. You can call len(args). Well, at least I was right that there's a better way.

Harriet Carker fucked around with this message at 07:41 on Mar 6, 2015

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

JawnV6 posted:

e: is select what I should be using for this?

Pretty much. It's how Linux programs traditionally handle asynchronous events while being single threaded, and multi-threaded python is less than ideal.

duck monster
Dec 15, 2004

The pyserial library has some really good examples along the lines your pursuing (Including select based)

Jose Cuervo
Aug 25, 2004
I have the following code
Python code:
import pandas as pd

def my_func(df, output_path):
    df.to_csv(output_path)


if __name__ == "__main__":
    df = pd.DataFrame({'a': [1,2,3,4,5], 'b': [1,2,3,4,5]})
    my_func(df, 'my_csv.csv')
and PyCharm throws the "Shadows name in outer scope" message for the df in my_func(df, ...). However, I thought that the scope of the code below the " if __name__ == "__main__" " part had a different scope to the function I defined. Can someone explain what is going on?

Dominoes
Sep 20, 2007

if __name__ == "__main__" is in the global scope, so like any if statement, if it gets executed, df would be defined as a global variable.

Python code:
def my_func():
    print(df)

if True:
    df = 'hi'
If you import a module with the above code and run my_func(), it'll print 'hi'. df would get assigned when you import the module; before you run my_func().

Dominoes fucked around with this message at 01:36 on Mar 7, 2015

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

It's worth noting that Python IDE's have to do some guessing for type hinting and scope and what not. Sometimes they guess wrong.

I don't really see what's wrong with your code, and I don't think PyCharm would guess that wrong, so my best guess is there's some code you're not posting?

Adbot
ADBOT LOVES YOU

evensevenone
May 12, 2001
Glass is a solid.

Edison was a dick posted:

Pretty much. It's how Linux programs traditionally handle asynchronous events while being single threaded, and multi-threaded python is less than ideal.

Why do people say this? If the threads are waiting on IO like this question is about it's fine. That covers about 98% of actual use cases for threading.

Even if it's CPU, it's not actually a problem, it's just that threads can't actually run concurrently. It's not going to be worse than a single-threaded program, aside from implementation inefficiencies.

  • Locked thread