Tuesday, December 25, 2012
Saturday, July 21, 2012
I am delighted to announce the first stable release of gtumbler (formerly gistiller), a new graphical PDF manager completely written in Python. It is distributed under the terms of the GNU GPL v3 license (the pyPDF python modules shipped with the app are distributed under a modified version of the BSD license). If you want to give it a try you can get it directly from my PPA "The Nest of Heliopolis" hosted by Launchpad. If you are using Ubuntu 12.04 Precise Pangolin, you can add my PPA to your APT sources list by simply typing
sudo apt-add-repository ppa:phoenix1987/ppa
sudo apt-get update
Then you can install gtumbler with the command
sudo apt-get install gtumbler
or directly from the Software Center.
The major features of gtumbler are:
Here is a screenshot of the application in action
Tuesday, November 29, 2011
I have a pretty old HP Pavilion dv1000 laptop with a Intel Pentium M Processor 740 at 1.7 GHz. I have always used Ubuntu along with the pre-installed version of Windows on that machine, but as new releases became more resource-hungry, I started to experience an unacceptable slowdown. Of course you can use a lighter window manager, such as Xcfe, but since I'm too affectionate to GNOME 2 I decided to make a new start with Debian. I then downloaded the latest 6.0.3 stable release and burnt it on a CD-RW (the other option is to boot the installer from the net, since it seems that you can't boot anything from removable USB media).
The installation process of my new OS went just fine, but in order to download updated packages from the internet I had to use my cable connection, since the Intel wifi adapter needed proprietary firmware that wasn't shipped with the first Debian CD. So I configured my ethernet card, and this turned out to be a source of problems, maybe the one you are experiencing now if you are reading this little guide. During the installation I had configured my ethernet to a static IP address, and everything went fine, Debian booted beautifully, fast and clean.
The first thing I did then was to install the Intel wifi adapter firmware in order to make my wifi card work properly. I have then enabled the non-free part of the official Debian repositories in my sources.list file and executed the following command
# apt-get update && apt-get install firmware-ipw2x00 wireless-tools
Then I have restarted the networking service and Network Manager with
# /etc/init.d/networking restart
# /etc/init.d/network-manager restart
At this point I configured my wireless connection with the graphical frontend to Network Manager (accessible through the icon in the notification area, usually near the clock on the top-right corner of the desktop) and...surprise! The association with the access point went just fine, but I couldn't ping my router nor any other machine on the local network. Weird, uh?
It turned out that this issue was related to the previous network configuration, the one carried out during the OS installation process, since in that case the installer wasn't supposed to use Network Manager to manage the connection. The solution is then pretty simple, I just had to edit my /etc/network/interfaces to look like the following minimal example
iface lo inet loopback
and after rebooting my wifi adapter started working like a charm again.
As a final remark I'd like to inform you that with Intel Wifi ipw2200 adapters you might need to use the firmware version 3.0 for the WEP security encryption. So the best thing to do is probably to move to a more secure encryption protocol, like WPA or WPA2.
Sunday, June 26, 2011
Referencer is a GNOME application especially designed for scientists, for it organizes any type of documents BiBTeX can handle, and ultimately allows you to export the whole collection into a single BiBTeX file (see this article @ Wikipedia and the project homepage for more details). Among the capabilities of Referencer there is the possibility of adding references from ID like the DOI code or the arXiv identifier. One feature that is still lacking is that of adding documents from web urls, although you can create an empty reference with only the field "url" filled. Since I'm currently working on my thesis for my Master's degree in Theoretical Physics, I need a plugin that instructs Referencer how to fetch books metadata from a web page containing the description of books. One of such sites is the fabled Google Books and in what follows I'm going to explain why I've chosen this particular site. If you search a book on Google Books, go on its details page (if you're in the preview page, just click on "About this book" on the left) and scroll down to the bottom of the page. There you'll find three buttons that will allow you export the bibliographic metadata in three different format. Fortunately one of such formats is BiBTeX, and Referencer is able to fill a document metadata from a bibtex file. I then wrote a plugin that allows to fetch this bibtex file from Google Books by pasting the address of the book into Referencer.
How to install the plugin:
- download the plugin file gbooks.py from here;
- put gbooks.py into directory ~/.referencer/plugin (you might need to create this folder);
- run Referencer and enable gbooks if not already enabled.
How to use this plugin:
- run Referencer and go to menu entry Documents->Add reference with ID...
- select Web URL from the dropdown menu
- paste the Google Books url in the text field and press OK
Sunday, January 16, 2011
|The main window of pyGtkPlot.|
Monday, January 3, 2011
subprocessdefines one class called
Popenthat basically created a two-way pipe between our parent process and a new child process, forked from the parent one and used to spawn the external application. This is just the standard fork/exec common practice and as it turns out it is exactly what we need to accomplish our task. But here comes the problem, as soon as we look at the methods of the class
Popen: just the
subprocess.Popen.communicate()method allows us to send data to the external application, read its response and then terminate it. But most of the time this is not what we want to do. We'd like to continuously send and receive data to and from the external application, so we'd like the connection to be kept open instead of being closed after the very first input ignition. Actually things are not this dramatic and we are indeed not to a dead end. Every instance of the class
subprocess.Popenhave attributes too, and among them we notice
.stderr. As claimed by the Python documentation, these three attributes are actually standard Python file objects, and this means that we can use their
write()methods to respectively read from and write to the external application in the child process. We can have access to these file objects only if we have passed
subprocess.PIPEto the corresponding arguments of the constructor of
subprocess.Popen, but I won't give much more details about this here because we will find everything later in the example code below. Here we shall convince ourself that if the child process has no available data to be read in the
stdoutstream, then calling its
read()method will cause our program to hang indefinitely, waiting for some data to show up at the reading end of the pipe. Here is the code to prove what we claimed. I'm assuming that you are running a Unix system and that you have the utility
catinstalled on your system. Now we open the python interpreter in a shell and we type in the following few lines of code
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess as subp >>> p = subp.Popen("cat",stdin=subp.PIPE,stdout=subp.PIPE) >>> p.stdin.write("Hello") >>> p.stdout.read(5) 'Hello' >>> p.stdout.read(1) ^CTraceback (most recent call last): File "<stdin>", line 1, in <module> KeyboardInterrupt >>>
catand we ask the constructor of
subprocess.Popento attach the
stdoutend to our parent process. We can thus write on and read from them, and a first step we write a string on the stream
catwill just echo out our string and send it back to us through its
stdout. In this case we are sure that there is data to be read from the stream
p.stdout, as shown by the string returned by
p.stdout.read(5). If we now try to read even only 1 more byte from the stream, the interpreter will hang indefinitely, waiting for something to read from
p.stdout, and the interpreter freezes, refusing to accept additional code. All that we can do at this point is send the
SIGINTsignal with the key combo
Ctrl+C. I suggest you to revisit this example, substituting the line
nis a integer greater than 5.
subprocess.Popenclass. Before working out the solution for the aforementioned issue, I kindly suggest you to check this web page out. As you can read from it, what we have encountered with the previous example is something that is well known among the team maintaining Python. So the solution we are going to work out might be just a temporary remedy. All we need is one low-level system call, namely
poll(), provided by the module
selectby means of the class
pollUnix system call waits until an event occurs at some set of file descriptors for a certain amount of time. We can use this feature to check if the stream associated to the
stroutend of the pipe has data ready to be read before actually reading it. Only if data is available we the proceed by reading from the stream, otherwise we skip this step, avoiding the locking of our process. Here follows a very simple example of a class,
Pipethat inherits from
subprocess.Popenand extends it with a few new methods, the most interesting of whom are certainly
import select import subprocess as subp class Pipe(subp.Popen): def __init__(self, exe, args = None, timeout = 0): self.timeout = timeout argv = [exe] if args != None: argv = argv + args subp.Popen.__init__(self, argv, stdin = subp.PIPE, stdout = subp.PIPE, stderr = subp.STDOUT) def close(self): self.terminate() self.wait() def write(self, data): poll = select.poll() poll.register(self.stdin.fileno(), select.POLLOUT) fd = poll.poll(self.timeout) if len(fd): f = fd if f > 0: self.stdin.write(data) def read(self, n = 1): poll = select.poll() poll.register(self.stdout.fileno(), select.POLLIN or select.POLLPRI) fd = poll.poll(self.timeout) if len(fd): f = fd if f > 0: return self.stdout.read(n) def readlines(self, n = 1): c = self.read() string = "" while c != None: string = string + str(c) c = self.read() return string def set_timeout(self, timeout): self.timeout = timeout
read()because the other two methods are then straightforward to understand. Here we single it out from the rest of the code
def read(self, n = 1): poll = select.poll() poll.register(self.stdout.fileno(), select.POLLIN or select.POLLPRI) fd = poll.poll(self.timeout) if len(fd): f = fd if f > 0: return self.stdout.read(n)
select.poll(). Its method
select.poll.register()registers a file descriptor with the specified flags, i.e. instructs the method
select.poll.poll()(see below) to watch the stream associated with the file descriptor for the occurrence of the events indicated by the flags. Then the method
select.poll.poll()starts watching the registered file descriptors for an amount of time specified by its argument. If all the file descriptors are ready, then the method returns, even if the whole timeout interval hasn't elapsed, and the return value is a list containing 2-tuples
(fd, event)for each file descriptor that has earlier been registered. Otherwise the method stops the execution until the timeout is reached, and the returns a (possibly empty) list of all the file descriptors that have been found ready for I/O operations. This is the most general behaviour of the method
select.poll.poll(). In the case that we are now analyzing we deal with only one file descriptor, namely the one associated with the stream
self.stdout. As you can see from the code, the way to obtain the file descriptor associated to a file object is to call its method
fileno(). With the first
ifwe check if the method
poll()has returned any file descriptor (it would be our file descriptor since we have registered only one of them). The second
ifchecks that a valid event has occurred on the file descriptor, just to be even more sure that everything's going to be fine, and this being the case we finally perform our reading operation.
pipe.Pipe.read(), when called with no arguments, reads at most 1 byte. The reason for this default behavior must be clear to you at this point. With the very first example above in mind, we shall rest to think on the fact that the method
poll()tells us whether there is data available on the stream, but not how much data is ready to be read. We can be sure that at least a byte is available for us, but by no means we can be sure that more than a byte is available on the stream. This implies that reading just a byte is the safest thing we can do. This gives a sense to the existence of the method
pipe.Pipe.readlines(). It reads from the
stdoutend, byte-by-byte, until no more data is available on the stream. Then the method returns a string with all the bytes read.
pipe.Pipe.write()looks so similar to
.read(). In most of the cases the
stdinend of the pipe will always be ready for I/O operations, and we really don't need to care too much about this issue. But it can happen (as a fact of life) that the stream associated
stdinis temporary unable to receive data from our program. This again would cause the parent process to hang until the data can be written successfully on the stream. A way to avoid this issue is again to make use of the
poll()system call, and this explains why
pipe.Pipe.read()look so similar to each other.
pipe.Pipe. Here is a very basic example, using again
#!/usr/bin/env python import pipe import sys if __name__ == "__main__": # Execute cat p = pipe.Pipe("cat", timeout = 100) # Try to read something. At this stage no data should be ready to be read print 'Reading %s' % p.readlines() # If the execution did not hang, the following line is executed p.write("Hello World!") # Now some data should be available print 'Reading %s' % p.readlines() p.close()
Monday, December 27, 2010
Saturday, December 25, 2010
# latexmath2png.py, created by Kamil Kisie
# (that you can find at the end of this file)