Is this a valid use of 'import'?

F

Frank Millman

Hi all

I am familiar enough with the normal use of 'import'. However, I have
found a use for it which seems effective, but I have not seen it used
like this before, so I am not sure if there are any downsides.

I know that when a module is imported the first time, it is
'executed'. This normally entails setting up constants, classes,
functions, etc, that you want to make available to the importer.

In this particular case, when it is executed, it does a whole lot
more. It reads in some parameters, establishes a socket connection,
starts a thread, and starts monitoring the socket using select.select.
It also exposes some functions that disguise the complexity of reading
from and writing to the socket.

This enables me to write a 'client' program that look like this -

---------------------------
from Utils.client import *

connect(userid='frank',pwd='')
cust = getRecord(
company='chagford',table='ArCustomers',
column='CustNo',value='A001')
print cust
close()
---------------------------

As you can see, it makes writing a client program very easy.

Are there any problems with this approach?

Frank Millman
 
T

Tim Golden

Frank said:
In this particular case, when it is executed, it does a whole lot
more. It reads in some parameters, establishes a socket connection,
starts a thread, and starts monitoring the socket using select.select.
It also exposes some functions that disguise the complexity of reading
from and writing to the socket.

This is not, in general, a good idea, no matter how appealing!
There is some subtle stuff going on within the chain of imports,
and firing off a new thread is quite likely to confuse it in
nasty ways later on. Less attractive though it may be, you're
better off having a "startup" function or whatever and calling
that:

import Utils.client
Utils.client.startup ()

TJG
 
M

Matimus

Hi all

I am familiar enough with the normal use of 'import'. However, I have
found a use for it which seems effective, but I have not seen it used
like this before, so I am not sure if there are any downsides.

I know that when a module is imported the first time, it is
'executed'. This normally entails setting up constants, classes,
functions, etc, that you want to make available to the importer.

In this particular case, when it is executed, it does a whole lot
more. It reads in some parameters, establishes a socket connection,
starts a thread, and starts monitoring the socket using select.select.
It also exposes some functions that disguise the complexity of reading
from and writing to the socket.

This enables me to write a 'client' program that look like this -

---------------------------
from Utils.client import *

connect(userid='frank',pwd='')
cust = getRecord(
            company='chagford',table='ArCustomers',
            column='CustNo',value='A001')
print cust
close()
---------------------------

As you can see, it makes writing a client program very easy.

Are there any problems with this approach?

Frank Millman

If it works for you that is great. That module however probably isn't
very readable or easy to modify however. Also, you are hiding a lot of
the complexity in a place where it isn't expected. Chances are it
would be easy to do the same thing at the class level instead of the
module level by putting all of that setup into the __init__ method of
a class, which is the proper place to do that sort of thing. Making
your code look something like this:

from utils.client import Connection

conn = Connection(userid='frank', pwd='')
cust = conn.getRecord(
company='chagford',
table='ArCustomers',
column='CustNo',
value='A001'
)
print cust
conn.close()


Without seeing your other code it is difficult to know what the issues
might be. In general, this is what classes are for.

Matt
 
F

Frank Millman

This is not, in general, a good idea, no matter how appealing!
There is some subtle stuff going on within the chain of imports,
and firing off a new thread is quite likely to confuse it in
nasty ways later on. Less attractive though it may be, you're
better off having a "startup" function or whatever and calling
that:

import Utils.client
Utils.client.startup ()

TJG

Makes sense.

Thanks, Tim.

Frank
 
F

Fredrik Lundh

Frank said:
I know that when a module is imported the first time, it is
'executed'. This normally entails setting up constants, classes,
functions, etc, that you want to make available to the importer.

In this particular case, when it is executed, it does a whole lot
more. It reads in some parameters, establishes a socket connection,
starts a thread, and starts monitoring the socket using select.select.
It also exposes some functions that disguise the complexity of reading
from and writing to the socket.

This enables me to write a 'client' program that look like this -

---------------------------
from Utils.client import *

connect(userid='frank',pwd='')
cust = getRecord(
company='chagford',table='ArCustomers',
column='CustNo',value='A001')
print cust
close()
---------------------------

As you can see, it makes writing a client program very easy.

Are there any problems with this approach?

besides being fragile and not scalable and not thread-safe and
incompatible with introspection tools and utterly surprising for people
used to normal Python behaviour, and only marginally easier to write
than, say:

from Utils.client import Client

c = Client()
c.connect(userid='frank',pwd='')
cust = c.getRecord(
company='chagford',table='ArCustomers',
column='CustNo',value='A001')
print cust
c.close()

and some other problems that I cannot think of right now, you mean?

</F>
 
T

Terry Reedy

Frank said:
I know that when a module is imported the first time, it is
'executed'. This normally entails setting up constants, classes,
functions, etc, that you want to make available to the importer.

And every time thereafter, the module code is not executed*. So module
code should only be code you want executed exactly once, on first
import, and never again.
In this particular case, when it is executed, it does a whole lot
more. It reads in some parameters, establishes a socket connection,
starts a thread, and starts monitoring the socket using select.select.
It also exposes some functions that disguise the complexity of reading
from and writing to the socket.

What if you want to open another connection, because you want a second,
or because you closed the first (to help the server while the client
does something else) or because the connection got dropped because the
server timed it out or because of network congestion or whatever?

tjr

*Python2 has a built-in reload function, but in 3.0 it is removed
because it almost never did what people wanted or expected and thus lead
to surprising bugs. You can delete a module from sys.modules and
re-import it, but the module object and those it created will not
disappear as long as there are other references to them.
 
B

Benjamin

*Python2 has a built-in reload function, but in 3.0 it is removed
because it almost never did what people wanted or expected and thus lead
to surprising bugs.  You can delete a module from sys.modules and
re-import it, but the module object and those it created will not
disappear as long as there are other references to them.

It's not gone. It's been moved to imp.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top