Question about StringIO

F

Frank Millman

Hi all

I understand that StringIO creates a file-like object in memory.

Is it possible to invoke another program, using os.system() or
os.popen(), and use the < redirect operator, so that the other program
reads my StringIO object as its input?

I will provide more details if required, but hopefully this is enough
for a simple yes or no answer, and if so, how.

BTW, I have tried using popen2() and passing my data via stdin, but the
other program (psql) does not react well to this - again, I will give
more info if necessary.

Thanks

Frank Millman
 
S

Steve Holden

Frank said:
Hi all

I understand that StringIO creates a file-like object in memory.

Is it possible to invoke another program, using os.system() or
os.popen(), and use the < redirect operator, so that the other program
reads my StringIO object as its input?

I will provide more details if required, but hopefully this is enough
for a simple yes or no answer, and if so, how.

BTW, I have tried using popen2() and passing my data via stdin, but the
other program (psql) does not react well to this - again, I will give
more info if necessary.
Unfortunately the StringIO module only creates instances inside the
process they are called: these objects have no existence to the
operating system or to other processes, and so can't be used for
inter-process communication.

regards
Steve
 
D

Diez B. Roggisch

Frank said:
Hi all

I understand that StringIO creates a file-like object in memory.

Is it possible to invoke another program, using os.system() or
os.popen(), and use the < redirect operator, so that the other program
reads my StringIO object as its input?

No. Processes don't share memory - thus you have to either use a temp
file, or pipes.
BTW, I have tried using popen2() and passing my data via stdin, but the
other program (psql) does not react well to this - again, I will give
more info if necessary.

Better do so :)

Diez
 
F

Frank Millman

Diez said:
No. Processes don't share memory - thus you have to either use a temp
file, or pipes.


Better do so :)

Diez

Thanks, Steve and Diez, for the replies. I didn't think it was
possible, but it was worth asking :)

I will try to explain my experience with popen() briefly.

I have some sql scripts to create tables, indexes, procedures, etc. At
present there are about 50 scripts, but this number will grow. I have
been running them manually so far. Now I want to automate the process.

I am supporting PostgreSQL and MS SQL Server, and the syntax is
slightly different in some cases. Rather than maintain two sets of
scripts, I prefix some lines with -pg- or -ms- to indicate the
platform, and then use Python to parse the scripts and generate a
correct output for each platform, passing it to 'psql' and 'osql'
respectively, using popen().

I have had a few problems, but it would take too long to describe them
all, and I just want a working solution, so I will focus on my latest
attempt.

I run through all the scripts and create a StringIO object with the
string I want to pass. It is about 250 000 bytes long. If I run psql
using popen(), and pass it the string via stdin, it works fine, but I
get all the messages on the screen. If I do the same, but end the
command with ' > fjm 2>&1' it works correctly and the messages end up
in the file fjm, which is about 40 000 bytes long. If I run it with
popen4(), it starts ok, but then hangs about 1/4 of the way through.
Exactly the same happens on MSW. It seems to be hitting a limit on the
size of the stdout file - is that possible?

For my purposes, I will be happy to use popen() and a choice of no
redirection, redirect to a file, or redirect to /dev/null. The question
about popen4() is therefore academic, though I would be interested to
know the answer.

BTW, is there an equivalent of /dev/null on MSW?

Thanks in advance for any suggestions.

Frank
 
B

Benjamin Niemann

Frank said:
I will try to explain my experience with popen() briefly.

I have some sql scripts to create tables, indexes, procedures, etc. At
present there are about 50 scripts, but this number will grow. I have
been running them manually so far. Now I want to automate the process.

I am supporting PostgreSQL and MS SQL Server, and the syntax is
slightly different in some cases. Rather than maintain two sets of
scripts, I prefix some lines with -pg- or -ms- to indicate the
platform, and then use Python to parse the scripts and generate a
correct output for each platform, passing it to 'psql' and 'osql'
respectively, using popen().

I have had a few problems, but it would take too long to describe them
all, and I just want a working solution, so I will focus on my latest
attempt.

I run through all the scripts and create a StringIO object with the
string I want to pass. It is about 250 000 bytes long. If I run psql
using popen(), and pass it the string via stdin, it works fine, but I
get all the messages on the screen. If I do the same, but end the
command with ' > fjm 2>&1' it works correctly and the messages end up
in the file fjm, which is about 40 000 bytes long. If I run it with
popen4(), it starts ok, but then hangs about 1/4 of the way through.
Exactly the same happens on MSW. It seems to be hitting a limit on the
size of the stdout file - is that possible?

For my purposes, I will be happy to use popen() and a choice of no
redirection, redirect to a file, or redirect to /dev/null. The question
about popen4() is therefore academic, though I would be interested to
know the answer.

That's probably a deadlock as described in
BTW, is there an equivalent of /dev/null on MSW?

Dunno - but as a last resort, you could create a tempfile with a unique name
(to be sure, not to override any existing data), dump your output there and
later os.unlink() it...
 
D

Diez B. Roggisch

Thanks, Steve and Diez, for the replies. I didn't think it was
possible, but it was worth asking :)

I will try to explain my experience with popen() briefly.

I have some sql scripts to create tables, indexes, procedures, etc. At
present there are about 50 scripts, but this number will grow. I have
been running them manually so far. Now I want to automate the process.

I am supporting PostgreSQL and MS SQL Server, and the syntax is
slightly different in some cases. Rather than maintain two sets of
scripts, I prefix some lines with -pg- or -ms- to indicate the
platform, and then use Python to parse the scripts and generate a
correct output for each platform, passing it to 'psql' and 'osql'
respectively, using popen().

Why don't youn use te python DB-Api instead?


Regards,

Diez
 
F

Frank Millman

Benjamin said:
That's probably a deadlock as described in
<http://docs.python.org/lib/popen2-flow-control.html>

Thanks for this pointer. I have read it, but I don't think it applies
to my situation, as it talks about 'reading' from the child's stdout
while the child is 'writing' to stderr. I am not doing that, or at
least not consciously. Here is a code snippet. 's' is a StringIO object
that contains my input. It is about 6000 lines/250000 bytes long.

-------------

sql_stdin,sql_stdout = os.popen4('psql -U %s -d %s' % (user,database))

sql_stdin.writelines(s.readlines())
s.close()
sql_stdin.close()

-------------

It starts, and then hangs, after processing about 6% of my input.

If I add ' > fjm 2>&1' to the command, it works, so it is definitely
connected with the child writing to stdout/stderr.

I tried storing my input in a list, and passing ''.join(s), but it had
the same result. I also looped over the list and wrote one line at a
time to sql_stdin - same result.

I can work around this, so a solution is not critical. However, it
would be nice to know if this is a limitation of popen4(), or if I am
doing something wrong.
Dunno - but as a last resort, you could create a tempfile with a unique name
(to be sure, not to override any existing data), dump your output there and
later os.unlink() it...

A quick google revealed the answer - there is a device called NUL which
achieves the same purpose.

Thanks

Frank
 
F

Frank Millman

Diez said:
Why don't youn use te python DB-Api instead?


Regards,

Diez

My scripts are used to create the tables in the database. I didn't
think that DB-API covered that. However, even if it did, I don't think
it would handle differences such as the following.

For Unicode support, PostgreSQL uses the character-set specified when
the database is created. SQL Server allows you to specify it for each
column, using the datatype NCHAR and NVARCHAR instead of CHAR and
VARCHAR.

PostgreSQL uses data types called DATE and TIMESTAMP. SQL Server uses
DATETIME (it also uses TIMESTAMP, but that is used for something else).

Both DBMS's have the concept of a column which is automatically
assigned a 'next number' each time a row is created, but the syntax for
defining the column is completely different.

PostgreSQL allows the use of a WHERE clause when creating an INDEX,
which is useful if you only want to index a subset of a table.

SQL Server has the concept of a CLUSTERED INDEX, whereby it stores the
rows physically in index sequence. It defaults to using a clustered
index for the primary key. Often this is not what you want, so it is
desirable to specify the primary key as NONCLUSTERED, and then specify
a CLUSTERED index for a more frequently used column.

These are just a few of the differences, but you get the idea. If there
is a better way to do this in a cross-platform manner, I would love to
know how.

Thanks

Frank
 
D

Diez B. Roggisch

Thanks for this pointer. I have read it, but I don't think it applies
to my situation, as it talks about 'reading' from the child's stdout
while the child is 'writing' to stderr.

But that is exactly the point: the psql blocks because you don't read
away the buffered data. Start a thread, read that stdout/stderr and see
if things go smoothly.

Diez
 
D

Diez B. Roggisch

My scripts are used to create the tables in the database. I didn't
think that DB-API covered that.

The DB-Api covers executin arbirary SQL - either DDL or DML. It is
surely centered around DML, but that doesn't mean that its not usabel to
issue "create ..." statements.
>However, even if it did, I don't think
it would handle differences such as the following.

<snip>

All that has nocthing to do with teh API - you'd still need your
differentiated DDL - but the communication with the programs would go away.

Diez
 
F

Frank Millman

Diez said:
But that is exactly the point: the psql blocks because you don't read
away the buffered data. Start a thread, read that stdout/stderr and see
if things go smoothly.

Diez

Of course (kicks himself), it is obvious now that you have explained
it. I tried your suggestion and it works perfectly.

Many thanks

Frank
 
F

Frank Millman

Diez said:
The DB-Api covers executin arbirary SQL - either DDL or DML. It is
surely centered around DML, but that doesn't mean that its not usabel to
issue "create ..." statements.


<snip>

All that has nocthing to do with teh API - you'd still need your
differentiated DDL - but the communication with the programs would go away.

Diez

I understand. It certainly gives me an alternative approach - I will
experiment to see which suits my purpose best.

Many thanks for your assistance.

Frank
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,266
Messages
2,571,342
Members
48,018
Latest member
DelilahDen

Latest Threads

Top