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
JawnV6
Jul 4, 2004

So hot ...
It's already using subprocess.popen() to farm out some other I/O, was just trying to shoehorn in an extra serial port into something I knew was sorta shoddy to begin with.

Thanks for the help, I found the pyserial docs and have the skeleton. I need the second serial to actually send data to test if it works for real.

Adbot
ADBOT LOVES YOU

Jose Cuervo
Aug 25, 2004

Dominoes posted:

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().

Excellent. Your example showed me what I was missing. Thank you.

QuarkJets
Sep 8, 2008

Thermopyle posted:

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?

PyCharm guessed it right; as Dominoes pointed out, control statements like if and while do not have their own scope, so everything inside of an if block is in whatever scope that if block is in, which in this case is the global scope.

The "df" variable is being declared in the global scope and also in a function, so PyCharm threw a warning because sometimes that can be messy to deal with (for instance, if you thought that you were modifying a variable in one scope while in another)

SurgicalOntologist
Jun 17, 2004

I've noticed that too. It seems to me PyCharm could avoid the warning when the variable in the outer scope is passed into the inner scope explicitly, using the same name. Or is that still dangerous somehow?

QuarkJets
Sep 8, 2008

I don't think that it's dangerous that way, no, although there's still the small risk of getting your scopes confused during future edits. Most people can probably safely turn off that warning, though

Nippashish
Nov 2, 2005

Let me see you dance!
A better solution is to change

code:
if __name__ == '__main__':
    do
    things
into

code:
def main():
    do
    things

if __name__ == '__main__':
    main()
so that you don't have scope-weirdness going on in the first place.

Jose Cuervo
Aug 25, 2004

Nippashish posted:

A better solution is to change

code:
if __name__ == '__main__':
    do
    things
into

code:
def main():
    do
    things

if __name__ == '__main__':
    main()
so that you don't have scope-weirdness going on in the first place.

That stops the warning being thrown for me, and seems like the best solution. Thanks.

Thermopyle
Jul 1, 2003

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

QuarkJets posted:

PyCharm guessed it right; as Dominoes pointed out, control statements like if and while do not have their own scope, so everything inside of an if block is in whatever scope that if block is in, which in this case is the global scope.

The "df" variable is being declared in the global scope and also in a function, so PyCharm threw a warning because sometimes that can be messy to deal with (for instance, if you thought that you were modifying a variable in one scope while in another)

Oh yeah, durr. I got caught up in thinking about how IDE's have to guess and didn't think about the code.

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
Er. I would like a static method of a subclass to completely inherit from a superclass, but it invokes in there another static method which should be from the subclass, but there it references itself from the superclass. :psyduck: Context:

code:
class OneOperandProblem(Problem):
    op_from = models.IntegerField('From')
    op_to = models.IntegerField('To')

    class Meta:
        abstract = True

    def generate(self):
        num = randrange(self.op_from, self.op_to)
        if self.answer_from or self.answer_to:
            while True:
                answer = OneOperandProblem.give_correct_solution(num)
                fits = True
                if self.answer_from and answer < self.answer_from:
                    fits = False
                if self.answer_to and answer > self.answer_to:
                    fits = False
                if fits:
                    break
                else:
                    num = randrange(self.op_from, self.op_to)
        return num
    @staticmethod
    def give_correct_solution(problem):
        if type(problem) is not int:
            raise TypeError

class RootProblem(OneOperandProblem):
    @staticmethod
    def give_correct_solution(problem):
        OneOperandProblem.give_correct_solution(problem)
        return round(sqrt(problem), 2)
So, it would be perfect if RootProblem could use OneOperandProblem's generate as is, except replacing give_correct_solution there by its own. There's a slight hitch in that RootProblem's give_correct_solution references the method from OneOperandProblem, and I've stumbled upon classmethod, but I'm afraid that's not going to work here... Oh, I've been told that what I did in OneOperandProblem's give_correct_solution is a bad thing, so maybe I should just get rid of that, although I've always felt that it has its role to play in the overall funtioning. (It could be more evident in other parts of this project.)

KICK BAMA KICK
Mar 2, 2009

Without seeing how you use these classes I think you're just doing a bunch of weird stuff in general -- which is all part of the learning process, and you do seem to understand that so it's cool -- but why do you think @classmethod doesn't solve your problem? At first glance generate kinda looks like a class method conceptually (again, hard to say without knowing how you intend to interface with this code). Assuming answer_from and answer_to are class attributes rather than instance attributes (and I'm assuming they're inherited from Problem), like op_from and op_to, then generate doesn't seem to relate to an instance in any way and thus classmethod looks like the solution to your immediate question.

Python code:
@classmethod
def generate(cls):
    num = randrange(cls.op_from, cls.op_to)
    if cls.answer_from or cls.answer_to:
        while True:
            answer = cls.give_correct_solution(num)
            fits = True
            if cls.answer_from and answer < cls.answer_from:
                fits = False
            if cls.answer_to and answer > cls.answer_to:
                fits = False
            if fits:
                break
            else:
                num = randrange(cls.op_from, cls.op_to)
    return num
cls will refer to the class upon which generate was actually called; RootProblem.generate() will use that code and cls will always refer to RootProblem within -- so cls.give_correct_solution refers to RootProblem.give_correct_solution.

QuarkJets
Sep 8, 2008

supermikhail posted:

Er. I would like a static method of a subclass to completely inherit from a superclass

That's easy enough:

Python code:
class A(object):
    @staticmethod
    def foo():
        print "foo"

class B(A):
    @staticmethod
    def bar():
        A.foo()
        print "bar"
        
B.bar() // prints "foo bar"

supermikhail posted:

but it invokes in there another static method which should be from the subclass, but there it references itself from the superclass. :psyduck: Context:

I don't understand this part of the sentence, and it's not made any clearer by the code that you posted. To me it looks like you have code that does what you want it to do: RootProblem has a give_correct_solution staticmethod that calls the give_correct_solution staticmethod from OneOperandProblem, its parent. Isn't that exactly what you wanted? Or are you saying that you want the generate method to invoke the give_correct_solution method from the subclass? You should be able to use @classmethod for that

supermikhail posted:

So, it would be perfect if RootProblem could use OneOperandProblem's generate as is, except replacing give_correct_solution there by its own. There's a slight hitch in that RootProblem's give_correct_solution references the method from OneOperandProblem, and I've stumbled upon classmethod, but I'm afraid that's not going to work here... Oh, I've been told that what I did in OneOperandProblem's give_correct_solution is a bad thing, so maybe I should just get rid of that, although I've always felt that it has its role to play in the overall funtioning. (It could be more evident in other parts of this project.)

Use @classmethod

QuarkJets fucked around with this message at 17:54 on Mar 8, 2015

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
First, oh crap, I have carelessly posted Django code without any explanation (this question is Python-general though, you'll probably agree). My sincerest apologies!

Second, generate unfortunately relies on instance-specific variables, which op_from, op_to, answer_from, and answer_to are. :blush: Ya know, I probably should rename the superclass methods such as give_correct_solution into their own method like check_problem_input, because it really kind of functions like its own method, and all children are supposed to override it... Er, I'll see how it goes and come back here, if that's alright?

foonykins
Jun 15, 2010

stop with the small talk


So I'm coding a very simple program involving sockets for my networking class. I have the code working fine on localhost, but running the program from my computer to contact the server at school just ends up hanging. I was hoping you guys could determine if it's a networking issue I need to figure out or if it's a flaw in my code.

Server side:
code:
from socket import *

serverPort = ('', 6445)

serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(serverPort)
print ("Server ready to receive packets")
while 1:
        b, clientAddress = serverSocket.recvfrom(2048)
        message = b.decode('ascii')
        print ( "Message received :"  + message)
        modifiedMessage = message.upper()
        b = modifiedMessage.encode('ascii')
        serverSocket.sendto(b,clientAddress)
        print ( "Message sent!!:" + modifiedMessage)
Client side:
code:
from socket import *

serverName = "afsconnect1.njit.edu"
serverPort = 6445
clientSocket = socket(AF_INET,SOCK_DGRAM)
message = input("input a lowercase sentence :")
clientSocket.sendto(message.encode('ascii'),(serverName,serverPort))
b, serveraddress = clientSocket.recvfrom(2048)
modifiedMessage = b.decode('ascii')
print (modifiedMessage)
clientSocket.close()

KICK BAMA KICK
Mar 2, 2009

supermikhail posted:

First, oh crap, I have carelessly posted Django code without any explanation (this question is Python-general though, you'll probably agree). My sincerest apologies!

Second, generate unfortunately relies on instance-specific variables, which op_from, op_to, answer_from, and answer_to are. :blush: Ya know, I probably should rename the superclass methods such as give_correct_solution into their own method like check_problem_input, because it really kind of functions like its own method, and all children are supposed to override it... Er, I'll see how it goes and come back here, if that's alright?
OK, guessed that might be Django from the models.IntegerField but I don't actually know how these concepts work in Django. So I might not be helpful but I am curious -- which of these classes get instantiated and what does an instance represent? That's what I can't figure out.

What would make sense to me, just from the names and what I remember of you explaining the application in the past, is that Problem and the nOperandProblems are essentially abstract base classes that provide some common attributes and define interfaces but are never instantiated. The specific type of problems like RootProblem that inherit from nOperandProblem are the things that get instantiated -- each provides values for some of those common attributes (like minimum or maximum values) and implements functionality according to that interface (like a method returning the solution for a given input). Each instance of a RootProblem would represent a single question, like "What is the square root of 2?" But I can't tell if that's what you're doing, and how Django concepts play into this.

I thought your generate method looked like an ad-hoc factory method -- a method that generates instances of the class on which it is defined -- written by someone who was just figuring out the factory pattern on their own without really knowing it was a thing yet, and factory methods are implemented as class methods, so that's part of why my mind went there. But if those attributes are instance attributes (presumably to be persisted via Django's ORM) then I'm not sure how this is supposed to work.

KICK BAMA KICK fucked around with this message at 18:47 on Mar 8, 2015

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
I don't remember what I've asked where anymore. :(

You're correct as far as what gets and what doesn't get instantiated. But each instance of RootProblem, say, represents a range (of op and answer). As an example, this terminal output:
code:
>>> p = RootProblem(op_from = 4, op_to = 100, answer_from = 2, answer_to = 10)
>>> p
<RootProblem: sqrt {4:100}   = {2:10}>
>>> p.generate()
21
Each problem instance also has a parameter "difficulty"... which I've failed to demonstrate in this example, but which that range corresponds to, such that on the actual Django page you can select a difficulty, it fetches an instance of a problem for that difficulty from the database, and that instance generates a number (in this case) for you to solve.

Well, all the aforementioned changes, plus making give_correct_solution a class method seem to have done the trick. Thanks for your input, fellas.

KICK BAMA KICK
Mar 2, 2009

Oh -- in that case I would name all those classes as ...ProblemSet and the method as generate_problem, but do whatever makes sense to you.

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
You're probably right. And I have a whole bunch of manual refactoring ahead of me anyway.

'ST
Jul 24, 2003

"The world has nothing to fear from military ambition in our Government."

foonykins posted:

So I'm coding a very simple program involving sockets for my networking class. I have the code working fine on localhost, but running the program from my computer to contact the server at school just ends up hanging. I was hoping you guys could determine if it's a networking issue I need to figure out or if it's a flaw in my code.
You're not calling listen or accept on the server socket. Not sure how that would still work on localhost.

I wouldn't be surprised if it was a network configuration issue with your school.

Another thing that's hit me before is trying to bind a server socket on a port that already has a bound connection.

Try using some of the socket setup code from the "Echo server program" at https://docs.python.org/2/library/socket.html

caberham
Mar 18, 2009

by Smythe
Grimey Drawer
Hey guys, I barely understand what's going on but I'm having a lot of fun learning Python and flask.

I do have a logic question though and appreciate any help.

Right now I'm trying to write a ticker which goes from deci second increments into a digital time format.

code:
Test cases

format (7) outputs 0:00.7
format (600) outputs 1:00.0
format(4567) --> 2:12.5
format(5999) --> 7:36.7
format(6000) --> 9:59.9
I'm having trouble dealing with some modulus division and this is a my attempt

code:
def format(timer) :
#1    decimal_second_mark = timer % 10
#2   one_second_mark = (timer % 100) // 10
#3   ten_second_mark = (timer // 1000) % 60
#4    minute_mark = (timer // 600)
My line #3 has faulty logic and im just kind of stuck. Really appreciate if someone can correct line 3

QuarkJets
Sep 8, 2008

Instead of messing with this, you should use the datetime module

Python code:
import 
x = datetime.timedelta(microseconds=timer*10000))
print str(x)
Also, don't use // for division, just use /

caberham
Mar 18, 2009

by Smythe
Grimey Drawer
I should be more specific, it's for some coursera homework assignment :eng99:

the ticker has to go up in 0.1 seconds and we have to convert the ticker value into a string so that some other handler can draw it

Stringent
Dec 22, 2004


image text goes here
code:
def format(timer) :
#1    decimal_second_mark = timer % 10
#2   one_second_mark =((timer / 10) % 60) / 10
#3   ten_second_mark = ((timer / 10) % 60) % 10
#4    minute_mark = (timer // 600)

Stringent
Dec 22, 2004


image text goes here
Also QuarkJets is right you want to be using this: https://docs.python.org/2/library/datetime.html#datetime.datetime.strftime

*edit* you may also want to look over https://docs.python.org/2/library/datetime.html#datetime.timedelta

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

caberham posted:

Hey guys, I barely understand what's going on but I'm having a lot of fun learning Python and flask.

I do have a logic question though and appreciate any help.

Right now I'm trying to write a ticker which goes from deci second increments into a digital time format.

code:
Test cases

format (7) outputs 0:00.7
format (600) outputs 1:00.0
format(4567) --> 2:12.5
format(5999) --> 7:36.7
format(6000) --> 9:59.9
I'm having trouble dealing with some modulus division and this is a my attempt

code:
def format(timer) :
#1    decimal_second_mark = timer % 10
#2   one_second_mark = (timer % 100) // 10
#3   ten_second_mark = (timer // 1000) % 60
#4    minute_mark = (timer // 600)
My line #3 has faulty logic and im just kind of stuck. Really appreciate if someone can correct line 3

Your logic is fine up until the 3rd one, where you suddenly change what you're doing (the numbers are slightly wrong too)

Just to outline what's happening, integer division (//) divides by a number and ignores the remainder, while modulo ignores the division result and gives you the remainder instead. You can use both to kind of split values on a numerical boundary, and work out how much you have on each side, which is what you're doing here.

#1 is easy, you're getting everything below 10 deciseconds. #2 is slightly more complex - you're getting everything below 100 deciseconds (i.e. the last two digits), then using integer division to reduce that to a single digit and ignore the remainder. Anything 100 or above is the business of the next digit, and anything below 10 is the business of the previous digit. So you're slicing and dicing to get the value that pertains to digit 2 (we're going from right to left)

Hopefully you understand that since your algorithm already does that! You just need to apply the same logic to digit 3. If you look at your code you're actually dividing first this time. A value of 599 deciseconds should be returning 5 for this stage, but right off the bat you're dividing by 1000 and discarding the remainder, which gives you 0 before it even hits the modulo. You need to use modulo to remove the excess values and division to remove the lower ones. And 1000 is the wrong number anyway - maybe think of it like an analogue meter, what value ticks over and adds 1 to the next digit?

caberham
Mar 18, 2009

by Smythe
Grimey Drawer
Thanks alot goons, stringent if i go to Osaka I will buy you a beer

Stringent posted:

code:
def format(timer) :
#1    decimal_second_mark = timer % 10
#2   one_second_mark =((timer / 10) % 60) / 10
#3   ten_second_mark = ((timer / 10) % 60) % 10
#4    minute_mark = (timer // 600)

God loving drat it I'm so dumb. Shouldn't have trial and error it both the ones and the tens of the seconds are base 60 so that's why I need to use modulo.

Fun fact though

it's

code:
    decimal_second_mark = timer % 10
   one_second_mark =   ((timer / 10) % 60) [b]% 10 [/b]
    ten_second_mark =   ((timer / 10) % 60) [b]/ 10[/b]
    minute_mark = (timer // 600)
There's a test case here : http://www.codeskulptor.org/#user39_QPmTaOZHwE_1.py The ones and tens got swapped :downsrim:

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

caberham posted:



God loving drat it I'm so dumb. Shouldn't have trial and error it both the ones and the tens of the seconds are base 60 so that's why I need to use modulo.

Well not really, the ones are base 10, that's why the tens are... well, tens. What stringent's doing there is getting the deciseconds for the first digit, then dividing by 10 to convert to seconds and doing modulo 60 to eliminate any full minutes, so you're only left with the remaining seconds. Then you can split that again into ones and tens for the separate digits

You don't have to do it that way, you can just //10 to lop off the deciseconds and %10 to remove the tens and up, and you're left with the ones. And //100 will remove the decis and ones, %6 will remove anything above 5, and then you've got your tens digit

You can do it any way that helps you keep track of what's happening (nothing wrong with treating two digits as a base 60 number if you want to), it's just useful to understand the general case and how you can use division and modulo to break off pieces and split numbers into whatever component parts or groupings you like

baka kaba fucked around with this message at 10:09 on Mar 10, 2015

caberham
Mar 18, 2009

by Smythe
Grimey Drawer
So many ways to skin a cat huh? Hey guys, thanks for everyone's help! Finished with my stop watch

have a go!

http://www.codeskulptor.org/#user39_LCkCOlDrkt_7.py

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
you should also investigate the divmod function, it's p cool

QuarkJets
Sep 8, 2008

Depending on the wording of your assignment, you might also not need to worry about computing the tens digit separately. You could create a string that is <number of minutes> : <number of seconds, base 60> . <tenths of seconds, base 10>. Does the assignment explicitly say that you have to compute each digit separately, or are you free to return a string calculated in any way that you want? As a former grader, I would probably give bonus points to a student who recognized that some of the digits can be calculated as part of a single operation instead of calculate separately

Hughmoris
Apr 21, 2007
Let's go to the abyss!
For a 260,000 line log file, is the following the most efficient/quickest/best practice way to iterate line by line?
Python code:
with open('C:/work/hugeLog.txt') as f:
    for lines in f:
*Well, Python docs state that its good practice to go this route.

Hughmoris fucked around with this message at 00:09 on Mar 11, 2015

AlexG
Jul 15, 2004
If you can't solve a problem with gaffer tape, it's probably insoluble anyway.
That is a completely legit way to do it, very Pythonic, concise, and likely to perform well. Slurping the whole thing into memory would probably also be fine for a file of this size. (I don't know how long your lines are or what else is going on with your system, but "probably".)

Dominoes
Sep 20, 2007

I dunno, but the way you posted might be it.

AlexG posted:

Slurping the whole thing into memory would probably also be fine for a file of this size.
But not necessary.

namaste friends
Sep 18, 2004

by Smythe

Hughmoris posted:

For a 260,000 line log file, is the following the most efficient/quickest/best practice way to iterate line by line?
Python code:
with open('C:/work/hugeLog.txt') as f:
    for lines in f:
*Well, Python docs state that its good practice to go this route.

Do you need to do f.readlines() ?

motorcyclesarejets
Apr 24, 2007

Cultural Imperial posted:

Do you need to do f.readlines() ?

'f.readlines()' will read the entire file into memory. If you do 'for line in f', you process each line as you read it.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
In order to have a truly reproducible build, I have to specify all dependencies in my requirements.txt, correct? As in, even the dependencies of dependencies...otherwise an untested version of something down the dependency graph could be installed?

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS

fletcher posted:

In order to have a truly reproducible build, I have to specify all dependencies in my requirements.txt, correct? As in, even the dependencies of dependencies...otherwise an untested version of something down the dependency graph could be installed?

Yes. Once you have all of your requirements installed correctly just run pip freeze > requirements.txt and pip will write your dependency graph as a flat list of requirements.

SurgicalOntologist
Jun 17, 2004

That's the way if your project is an app/website/data analysis (which it sounds like it is in your case), but it's worth noting that if you're writing a library, it's better to just list direct dependencies in setup.py (you can also put a dummy requirements.txt that basically says "check setup.py"). Like I said I don't think it applies here but I've come across a few small libraries that caused dependency headaches due to someone doing pip freeze > requirements.txt.

duck monster
Dec 15, 2004

Honestly, even if its just to keep a list around of how you set up your build, requirements.txt is a bloody useful thing to do. I've totally wrecked builds before and being able to reanimate the corpse with requirements.txt is valuable.

Hell I put it on a precommit hook, just to be sure.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Blinkz0rz posted:

Yes. Once you have all of your requirements installed correctly just run pip freeze > requirements.txt and pip will write your dependency graph as a flat list of requirements.

Does it really put them all in the correct order of what depends on what?

edit: Guess not "packages are listed in a case-insensitive sorted order" so I guess I'd have to combine it with --no-deps when I go to install them somewhere else

fletcher fucked around with this message at 00:42 on Mar 12, 2015

Adbot
ADBOT LOVES YOU

SurgicalOntologist
Jun 17, 2004

duck monster posted:

Honestly, even if its just to keep a list around of how you set up your build, requirements.txt is a bloody useful thing to do. I've totally wrecked builds before and being able to reanimate the corpse with requirements.txt is valuable.

Hell I put it on a precommit hook, just to be sure.

Yeah, same. Like I said, the exception is just for libraries. In that case, you want to allow the user as much flexibility as possible, and you want to run your tests across different combinations of dependencies. In that situation having your precise environment set in stone can be counterproductive as a developer, and certainly for other developers looking to use your libray.

Personally, for non-library projects I make two files, conda-requirements.txt and pip-requirements.txt. It's awesome to be able to get the same environment up and running in 30 seconds. For library projects I develop in my root environment in which I install library updates as soon as they're available. Eventually I set up dependency matrices with tox/travis for testing.

In the end it depends on how your project is used. If it's something that will be imported, then pip freeze > requirements.txt is probably a bad idea. If it's something that will be built or launched or deployed, then it's probably the way to go.

  • Locked thread