views:

256

answers:

4

I was wondering how to make a python script portable to both linux and windows?

One problem I see is shebang. How to write the shebang so that the script can be run on both windows and linux?

Are there other problems besides shebang that I should know?

Is the solution same for perl script?

Thanks and regards!

+2  A: 

The shebang line will be interpreted as a comment by Perl or Python. The only thing that assigns it a special meaning is the UNIX/Linux shell; it gets ignored on Windows. The way Windows knows which interpreter to use to run the file is through the file associations in the registry, a different mechanism altogether.

David Zaslavsky
Note quite true. perl will look for flags in the shebang line. Try running a file containing `#! perl -p`
justintime
Indeed if you create a .pl file that starts `#! python` then perl will call python.
justintime
ah true, I forgot about that. (I'm too used to Python, which AFAIK does completely ignore the shebang line)
David Zaslavsky
+9  A: 

Windows will just ignore the shebang (which is, after all, a comment); in Windows you need to associate the .py extension to the Python executable in the registry, but you can perfectly well leave the shebang on, it will be perfectly innocuous there.

There are many bits and pieces which are platform-specific (many only exist on Unix, msvcrt only on Windows) so if you want to be portable you should abstain from those; some are subtly different (such as the detailed precise behavior of subprocess.Popen or mmap) -- it's all pretty advanced stuff and the docs will guide you there. If you're executing (via subprocess or otherwise) external commands you'd better make sure they exist on both platforms, of course, or check what platform you're in and use different external commands in each case.

Remember to always use /, not \, as path separator (forward slash works in both platforms, backwards slash is windows-only), and be meticulous as to whether each file you're opening is binary or text.

I think that's about it...

Alex Martelli
Better yet, use the `os.path.sep` constant as the path separator.
dan04
Thanks, Alex! If shebang is ignored in windows, then why there is this question "How do I ignore the Perl shebang on Windows with Apache 2?". See http://stackoverflow.com/questions/2036577/how-do-i-ignore-the-perl-shebang-on-windows-with-apache-2 .
Tim
@Tim, while Windows itself ignores the shebang, programs running under Windows can of course see that line - and just as that goes for a text editor so it does for a web server. Apache on Windows does its own shebang interpretation -- but dealing with that is a system administration problem about apache configuration, nothing to do with Python or indeed stackoverflow at all (it's a serverfault question).
Alex Martelli
+5  A: 

Make sure you don't handle files and directories as strings and simply concatenate them with a slash in between. Perl:

$path = File::Spec->catfile("dir1", "dir2", "file")

Remember that Windows has volumes:

($volume, $path, $file) = File::Spec->splitpath($full_path);
@directories = File::Spec->splitdir($path);

When running other programs, try to avoid involving the shell. In Perl, when you run a command with the system function, you can easily get it wrong with:

$full_command = 'C:\Documents and Settings/program.exe "arg1" arg2'; # spaces alert!
system($full_command);

Instead, you can run system with a list as argument: the executable and the arguments being separate strings. In that case, the shell doesn't get involved and you don't get into trouble regarding shell escaping or spaces in file names.

system('C:\Documents and Settings/program.exe', 'arg1', 'arg2');

There's a bunch of portability nits documented in the perlport manual.

tsee
+2  A: 

I don't know enough to comment on Python approaches to this problem, so I won't.

Most things in Perl will just work. There are a few gotchas that are easy to avoid.

Here are a few things I have come across in the years I've been working with Win32 Perl:

  • Use 3 argument form of open. The two argument form can have problems with spaces in paths. (You should already be doing this anyway.)
  • Make sure that the case is correct when you use a module. use Warnings; will appear to work, but in reality it will fail.
  • select only works on actual sockets under Windows. You can't use it on any other sort of handle.
  • Use File::Spec to manage paths to files.
  • When you open a file handle CRLF will automatically be converted to LF line endings as the handle is read. LF is changed to CRLF on write. If you want to avoid this, use binmode on the handle to prevent the translation.
  • If you need to pass arguments through a shell, put double quotes around each argument. This will prevent errors due to spaces in file names.

See perlport for more information on individual functions.

daotoad