Is there Python equivalent to Perl BEGIN{} block?

A

Alex

Hi all,

The subject says pretty much all, i would very appreciate an answer. I
tried to search the various forums and groups, but didn't find any
specific answer...

Thanks,
Alex.
 
P

Paddy

Hi all,

The subject says pretty much all, i would very appreciate an answer. I
tried to search the various forums and groups, but didn't find any
specific answer...

Thanks,
Alex.

No not really.

There are lots of other ways to structure a Python program though
which makes its omission hardly felt.

- Paddy.
 
C

Carl Banks

Hi all,

The subject says pretty much all, i would very appreciate an answer. I
tried to search the various forums and groups, but didn't find any
specific answer...

Python technically has no equivalent: you can't run code at compile
time. However, the BEGIN block in Perl seems to have been added to
work around some of Perl's nonlinear order of execution. Normally in
Python you don't need a BEGIN block: just put the code at the top of
you script/module and it will exectute before anything else.

Want to tell us what you need it for? Perhaps we can suggest a way of
doing it that's appropriate in Python.


Carl Banks
 
T

Tim Chase

The subject says pretty much all,

Given what I understand about the BEGIN block[1], this is how
Python works automatically:

bash$ cat a.py
print 'a1'
import b
print 'a2'

bash$ cat b.py
print 'b'

bash$ python a.py
a1
b
a2

However, the first import does win and Python caches
module-loading, so take care:

bash$ cat x.py
print 'one'
import a
print 'two'
import b
print 'three'

bash$ python x.py
one
a1
B
a2
two
three

-tkc

[1]
http://www.cs.cf.ac.uk/Dave/PERL/node133.html
 
J

Justus Schwabedal

What do you need it for anyway? I just read about it and I think it's
useless
in python.
 
C

Carl Banks

What do you need it for anyway? I just read about it and I think it's
useless
in python.


Perl, like Python, has a separate compilation and run times. One day,
someone who was trying to use Perl for something asked, "You know,
wouldn't it be neat-o if you could execute some Perl code *before* you
compiled the script?" And so (since that's usually enough reason to
add something to Perl) was borne the BEGIN block.

I believe the official rationale was that they wanted to add some
magic variables that affected Perl's compilation and couldn't do it
without a magic block that executed at compile time.

Python solved a similar problem by introducing __future__ imports.


Carl Banks
 
J

Jeff Schwab

Alex said:
The subject says pretty much all, i would very appreciate an answer. I
tried to search the various forums and groups, but didn't find any
specific answer...

I'd like an answer to this, too. In Perl, I mostly used it for
one-liners, when a variable needed to be initialized to some non-default
value; for example, perl -ple 'BEGIN { $sum = 42 } $sum += $_'.
 
P

Paddy

Perl, like Python, has a separate compilation and run times. One day,
someone who was trying to use Perl for something asked, "You know,
wouldn't it be neat-o if you could execute some Perl code *before* you
compiled the script?" And so (since that's usually enough reason to
add something to Perl) was borne the BEGIN block.

I believe the official rationale was that they wanted to add some
magic variables that affected Perl's compilation and couldn't do it
without a magic block that executed at compile time.

Python solved a similar problem by introducing __future__ imports.

Carl Banks

And theres me thinking it was part of Perls AWK compatibility code.

- Paddy.
 
A

Alex

Python technically has no equivalent: you can't run code at compile
time. However, the BEGIN block in Perl seems to have been added to
work around some of Perl's nonlinear order of execution. Normally in
Python you don't need a BEGIN block: just put the code at the top of
you script/module and it will exectute before anything else.

Want to tell us what you need it for? Perhaps we can suggest a way of
doing it that's appropriate in Python.

Carl Banks

Hi,

First of all thanks all for answering!

I have some environment check and setup in the beginning of the code.
I would like to move it to the end of the script. But I want it to
execute first, so the script will exit if the environment is not
configured properly.

Thanks,
Alex.
 
B

Bruno Desthuilliers

Alex a écrit :
(sni)
First of all thanks all for answering!

I have some environment check and setup in the beginning of the code.
I would like to move it to the end of the script.

Why ? (if I may ask...)
But I want it to
execute first, so the script will exit if the environment is not
configured properly.

If you want some code to execute first when the script/module is loaded,
then keep this code where it belongs : at the beginning of the script.
 
C

Carl Banks

Alex a écrit :
(sni)



Why ? (if I may ask...)


If you want some code to execute first when the script/module is loaded,
then keep this code where it belongs : at the beginning of the script.


I concur with Bruno's recommendation: stuff you want to do first
should come first in the script. Things like BEGIN blocks hurt
readability because you can't identify where execution begins without
reading the whole file.

Having said that, one thing that often happens in Python scripts is
that all the functions are defined first, then the script logic
follows. So you could put the meat of your script in a function, then
the "BEGIN" stuff after that functions:


def run_script():
#
# script contained in this long function
#

# Then test preconditions here...
if os.environ["HELLO"] != "WORLD":
sys.exit(2)

# Then call the run_script functions
run_script()


But having said THAT, I don't recommend you do that with
preconditions. If the script has a quick early exit scenario, you
really ought to put that near the top, before the function
definitions, to clearly show to a human reader what is necessary to
run the script.


Carl Banks
 
J

Jonathan Gardner

Perl, like Python, has a separate compilation and run times.  One day,
someone who was trying to use Perl for something asked, "You know,
wouldn't it be neat-o if you could execute some Perl code *before* you
compiled the script?"  And so (since that's usually enough reason to
add something to Perl) was borne the BEGIN block.

I believe the official rationale was that they wanted to add some
magic variables that affected Perl's compilation and couldn't do it
without a magic block that executed at compile time.

It's a bit different. Python's "import" and perl's "use" statements
aren't very similar at all. See, perl looks for any "use" statements
and runs those first. That's not the way for Python at all. It's ok to
import a module right before you need it in a function. If you never
call the function, you'll never import the module.

What if you want to reprogram the search path before you use a module?
Well, in Python, you just work on sys.path before the import
statement. But in perl, if you put a statement that mucks with the
perl path, then it will be ignored until it is too late. So you have
to throw it into the BEGIN block to have it do anything at all. What
was an obvious task in Python that uses only constructs and concepts
you already know about, requires a new concept and syntax that wasn't
needed before in perl.

Also, Jeff has it right. Those who don't get it should look closely at
the '-p' option passed to perl. (It has a cousin '-n' that is also
just as useful.) Here, he wants to initialize some code before the
loop starts, but he can't specify that initializing code outside of
the loop without a BEGIN block.

BEGIN is a dirty, ugly, stupid bandage to an underlying weakness in
perl. That is, there is magic that needs more magic to override it.
(And then you'll need magic to override the overriding magic, ad
infinitum.) Rather than adding more magic, what you really need to do
is get rid of magic that gets in people's way, or change the magic so
it is actually useful for everyone.

Python has it right. Tokenize, parse, (skip compile-link-import
magic), and run.

And leave out the magical -p and -n. If you want to iterate through a
file, "for line in sys.stdin:".
 
J

Jeff Schwab

Paddy said:
Or better still:

import fileinput
for line in fileinput.input():
process(line)

I write maybe a dozen one-liners a day. It's not practical to do this
with Python, or at least it's not nearly as convenient as Perl. I'm
fine with the magic. Abusing the magic is another story; Perl language
features are meant to be used in particular contexts, and BEGIN blocks
are rarely if ever necessary in Perl modules.
 
A

Aahz

I write maybe a dozen one-liners a day. It's not practical to do this
with Python, or at least it's not nearly as convenient as Perl.

That is a defensible position, but my take is that writing the one-liners
in Python is more convenient than remembering enough Perl to make writing
one-liners useful. Especially when the one-liners often start expanding.
 
A

Alex

Sure, because of a readability (similar to function declarations in
C).
If you want some code to execute first when the script/module is loaded,
then keep this code where it belongs : at the beginning of the script.

I concur with Bruno's recommendation: stuff you want to do first
should come first in the script. Things like BEGIN blocks hurt
readability because you can't identify where execution begins without
reading the whole file.

Having said that, one thing that often happens in Python scripts is
that all the functions are defined first, then the script logic
follows. So you could put the meat of your script in a function, then
the "BEGIN" stuff after that functions:

def run_script():
#
# script contained in this long function
#

# Then test preconditions here...
if os.environ["HELLO"] != "WORLD":
sys.exit(2)

# Then call the run_script functions
run_script()

But having said THAT, I don't recommend you do that with
preconditions. If the script has a quick early exit scenario, you
really ought to put that near the top, before the function
definitions, to clearly show to a human reader what is necessary to
run the script.

Carl Banks

Hi,

Maybe i was a little bit unclear... I meant that i wanted to do
something like this:

#!usr/bin/env python

check_env()

from subprocess import *

class MyClass:
# Class definition

def check_env():
# Code

if __name__ == "__main__":
# Script logic

The thing is, as i saw, that Python doesn't recognize the
"check_env()" function before it reaches the "def" statement.

I need the check to be done before the subprocess import, because our
customers use different Python versions, some of them do not have
subprocess module. So i want to exit if i see that Python version
being used doesn't have that module.

The solution to that problem with what you suggested could be wrapping
the subprocess import with function, am i correct?
 
A

Arnaud Delobelle

Sure, because of a readability (similar to function declarations in
C).


I concur with Bruno's recommendation: stuff you want to do first
should come first in the script.  Things like BEGIN blocks hurt
readability because you can't identify where execution begins without
reading the whole file.
Having said that, one thing that often happens in Python scripts is
that all the functions are defined first, then the script logic
follows.  So you could put the meat of your script in a function, then
the "BEGIN" stuff after that functions:
def run_script():
    #
    # script contained in this long function
    #
# Then test preconditions here...
if os.environ["HELLO"] != "WORLD":
    sys.exit(2)
# Then call the run_script functions
run_script()
But having said THAT, I don't recommend you do that with
preconditions.  If the script has a quick early exit scenario, you
really ought to put that near the top, before the function
definitions, to clearly show to a human reader what is necessary to
run the script.
Carl Banks

Hi,

Maybe i was a little bit unclear... I meant that i wanted to do
something like this:

#!usr/bin/env python

check_env()

from subprocess import *

class MyClass:
   # Class definition

def check_env():
   # Code

if __name__ == "__main__":
   # Script logic

The thing is, as i saw, that Python doesn't recognize the
"check_env()" function before it reaches the "def" statement.

I need the check to be done before the subprocess import, because our
customers use different Python versions, some of them do not have
subprocess module. So i want to exit if i see that Python version
being used doesn't have that module.

The solution to that problem with what you suggested could be wrapping
the subprocess import with function, am i correct?

why not:

try:
from subprocess import *
except ImportError:
sys.exit('No subprocess module :(')

# Rest of module
 
C

Carl Banks

Sure, because of a readability (similar to function declarations in
C).


I concur with Bruno's recommendation: stuff you want to do first
should come first in the script. Things like BEGIN blocks hurt
readability because you can't identify where execution begins without
reading the whole file.
Having said that, one thing that often happens in Python scripts is
that all the functions are defined first, then the script logic
follows. So you could put the meat of your script in a function, then
the "BEGIN" stuff after that functions:
def run_script():
#
# script contained in this long function
#
# Then test preconditions here...
if os.environ["HELLO"] != "WORLD":
sys.exit(2)
# Then call the run_script functions
run_script()
But having said THAT, I don't recommend you do that with
preconditions. If the script has a quick early exit scenario, you
really ought to put that near the top, before the function
definitions, to clearly show to a human reader what is necessary to
run the script.
Carl Banks

Hi,

Maybe i was a little bit unclear... I meant that i wanted to do
something like this:

#!usr/bin/env python

check_env()

from subprocess import *

class MyClass:
# Class definition

def check_env():
# Code

if __name__ == "__main__":
# Script logic

The thing is, as i saw, that Python doesn't recognize the
"check_env()" function before it reaches the "def" statement.


You could rearrange it like this and it will work:


#!usr/bin/env python

def check_env():
# Code

check_env()

from subprocess import *

class MyClass:
# Class definition

if __name__ == "__main__":
# Script logic


Or, better yet, do what Arnaud Delobelle suggests.


It's not a big deal to move imports down the page a bit, as long as
you throw in a few clear comments explaning what you're doing and why.

You might also consider putting check_env() in a separate module.


Carl Banks
 
A

Alex

Sure, because of a readability (similar to function declarations in
C).
But I want it to
execute first, so the script will exit if the environment is not
configured properly.
If you want some code to execute first when the script/module is loaded,
then keep this code where it belongs : at the beginning of the script.
I concur with Bruno's recommendation: stuff you want to do first
should come first in the script. Things like BEGIN blocks hurt
readability because you can't identify where execution begins without
reading the whole file.
Having said that, one thing that often happens in Python scripts is
that all the functions are defined first, then the script logic
follows. So you could put the meat of your script in a function, then
the "BEGIN" stuff after that functions:
def run_script():
#
# script contained in this long function
#
# Then test preconditions here...
if os.environ["HELLO"] != "WORLD":
sys.exit(2)
# Then call the run_script functions
run_script()
But having said THAT, I don't recommend you do that with
preconditions. If the script has a quick early exit scenario, you
really ought to put that near the top, before the function
definitions, to clearly show to a human reader what is necessary to
run the script.
Carl Banks

Maybe i was a little bit unclear... I meant that i wanted to do
something like this:
#!usr/bin/env python

from subprocess import *
class MyClass:
# Class definition
def check_env():
# Code
if __name__ == "__main__":
# Script logic
The thing is, as i saw, that Python doesn't recognize the
"check_env()" function before it reaches the "def" statement.

You could rearrange it like this and it will work:

#!usr/bin/env python

def check_env():
# Code

check_env()

from subprocess import *

class MyClass:
# Class definition

if __name__ == "__main__":
# Script logic

Or, better yet, do what Arnaud Delobelle suggests.

It's not a big deal to move imports down the page a bit, as long as
you throw in a few clear comments explaning what you're doing and why.

You might also consider putting check_env() in a separate module.

Carl Banks

Hi guys,

Thanks for help! :)
 

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

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top